├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .gitmodules ├── Doxyfile ├── LICENSE ├── Makefile ├── README.md ├── build.rabs ├── builddocs.sh ├── common.rabs ├── docgroups.mini ├── docs.xml ├── docs ├── .readthedocs.yaml ├── Makefile ├── _static │ ├── css │ │ └── custom.css │ └── js │ │ ├── custom.js │ │ ├── minilang.js │ │ ├── minilang.wasm │ │ └── minilang.wasm.map ├── _util │ └── minilang.py ├── api.rst ├── api │ ├── booleans.rst │ ├── cbor.rst │ ├── compiler.rst │ ├── enums.rst │ ├── externals.rst │ ├── flags.rst │ ├── functions.rst │ ├── init.rst │ ├── inthash.rst │ ├── iterators.rst │ ├── lists.rst │ ├── logging.rst │ ├── maps.rst │ ├── math.rst │ ├── methods.rst │ ├── modules.rst │ ├── names.rst │ ├── numbers.rst │ ├── objects.rst │ ├── runtime.rst │ ├── sets.rst │ ├── slices.rst │ ├── streams.rst │ ├── stringmap.rst │ ├── strings.rst │ ├── symbols.rst │ ├── tuples.rst │ └── types.rst ├── conf.py ├── docutils.conf ├── doxygen │ └── xml │ │ ├── Doxyfile.xml │ │ ├── combine.xslt │ │ ├── compound.xsd │ │ ├── coro_8h.xml │ │ ├── dap_8h.xml │ │ ├── dir_68267d1309a1af8e8297ef4c3efbcdba.xml │ │ ├── doxyfile.xsd │ │ ├── group__booleans.xml │ │ ├── group__cbor.xml │ │ ├── group__compiler.xml │ │ ├── group__enums.xml │ │ ├── group__externals.xml │ │ ├── group__flags.xml │ │ ├── group__functions.xml │ │ ├── group__init.xml │ │ ├── group__inthash.xml │ │ ├── group__iterators.xml │ │ ├── group__lists.xml │ │ ├── group__logging.xml │ │ ├── group__maps.xml │ │ ├── group__math.xml │ │ ├── group__methods.xml │ │ ├── group__modules.xml │ │ ├── group__names.xml │ │ ├── group__numbers.xml │ │ ├── group__objects.xml │ │ ├── group__runtime.xml │ │ ├── group__sets.xml │ │ ├── group__slices.xml │ │ ├── group__streams.xml │ │ ├── group__stringmap.xml │ │ ├── group__strings.xml │ │ ├── group__symbols.xml │ │ ├── group__tuples.xml │ │ ├── group__types.xml │ │ ├── index.xml │ │ ├── index.xsd │ │ ├── inthash2_8h.xml │ │ ├── inthash_8h.xml │ │ ├── linenoise_8h.xml │ │ ├── minilang_8h.xml │ │ ├── ml__array_8h.xml │ │ ├── ml__ast_8h.xml │ │ ├── ml__base16_8h.xml │ │ ├── ml__base64_8h.xml │ │ ├── ml__bytecode_8h.xml │ │ ├── ml__bytecode__jit_8h.xml │ │ ├── ml__cbor_8h.xml │ │ ├── ml__compiler2_8h.xml │ │ ├── ml__compiler_8h.xml │ │ ├── ml__console_8h.xml │ │ ├── ml__coroutine_8h.xml │ │ ├── ml__debugger_8h.xml │ │ ├── ml__expr__types_8h.xml │ │ ├── ml__file_8h.xml │ │ ├── ml__json_8h.xml │ │ ├── ml__library_8h.xml │ │ ├── ml__list_8h.xml │ │ ├── ml__logging_8h.xml │ │ ├── ml__macros_8h.xml │ │ ├── ml__map_8h.xml │ │ ├── ml__math_8h.xml │ │ ├── ml__method_8h.xml │ │ ├── ml__minijs_8h.xml │ │ ├── ml__mmap_8h.xml │ │ ├── ml__module_8h.xml │ │ ├── ml__number_8h.xml │ │ ├── ml__object_8h.xml │ │ ├── ml__opcodes_8h.xml │ │ ├── ml__polynomial_8h.xml │ │ ├── ml__pqueue_8h.xml │ │ ├── ml__runtime_8h.xml │ │ ├── ml__sequence_8h.xml │ │ ├── ml__set_8h.xml │ │ ├── ml__slice_8h.xml │ │ ├── ml__socket_8h.xml │ │ ├── ml__stream_8h.xml │ │ ├── ml__string_8h.xml │ │ ├── ml__struct_8h.xml │ │ ├── ml__table_8h.xml │ │ ├── ml__tasks_8h.xml │ │ ├── ml__thread_8h.xml │ │ ├── ml__time_8h.xml │ │ ├── ml__types_8h.xml │ │ ├── ml__uuid_8h.xml │ │ ├── ml__xe_8h.xml │ │ ├── ml__xml_8h.xml │ │ ├── sha256_8h.xml │ │ ├── stringmap_8h.xml │ │ ├── structSHA256__CTX.xml │ │ ├── structcoro__stack.xml │ │ ├── structinthash2__node__t.xml │ │ ├── structinthash2__result__t.xml │ │ ├── structinthash2__t.xml │ │ ├── structinthash__result__t.xml │ │ ├── structinthash__t.xml │ │ ├── structlinenoiseCompletions.xml │ │ ├── structml__address__t.xml │ │ ├── structml__array__dimension__t.xml │ │ ├── structml__array__t.xml │ │ ├── structml__boolean__t.xml │ │ ├── structml__call__state__t.xml │ │ ├── structml__cbor__result__t.xml │ │ ├── structml__cbor__t.xml │ │ ├── structml__cfunction__t.xml │ │ ├── structml__cfunctionx__t.xml │ │ ├── structml__class__t.xml │ │ ├── structml__closure__info__t.xml │ │ ├── structml__closure__t.xml │ │ ├── structml__comparison__state__t.xml │ │ ├── structml__context__t.xml │ │ ├── structml__debugger__t.xml │ │ ├── structml__decl__t.xml │ │ ├── structml__double__t.xml │ │ ├── structml__external__t.xml │ │ ├── structml__externals__t.xml │ │ ├── structml__factor__t.xml │ │ ├── structml__factors__t.xml │ │ ├── structml__field__info__t.xml │ │ ├── structml__field__t.xml │ │ ├── structml__hash__chain__t.xml │ │ ├── structml__inline__function__t.xml │ │ ├── structml__integer__interval__t.xml │ │ ├── structml__integer__range__t.xml │ │ ├── structml__integer__t.xml │ │ ├── structml__iter__state__t.xml │ │ ├── structml__list__iter__t.xml │ │ ├── structml__list__node__t.xml │ │ ├── structml__list__t.xml │ │ ├── structml__logger__t.xml │ │ ├── structml__macro__t.xml │ │ ├── structml__map__iter__t.xml │ │ ├── structml__map__node__t.xml │ │ ├── structml__map__t.xml │ │ ├── structml__method__cached__t.xml │ │ ├── structml__method__t.xml │ │ ├── structml__minijs__encoder__t.xml │ │ ├── structml__minijs__t.xml │ │ ├── structml__module__t.xml │ │ ├── structml__object__t.xml │ │ ├── structml__param__type__t.xml │ │ ├── structml__polynomial__rational__t.xml │ │ ├── structml__polynomial__t.xml │ │ ├── structml__queued__state__t.xml │ │ ├── structml__real__interval__t.xml │ │ ├── structml__real__range__t.xml │ │ ├── structml__reference__t.xml │ │ ├── structml__result__state__t.xml │ │ ├── structml__scheduler__t.xml │ │ ├── structml__set__iter__t.xml │ │ ├── structml__set__node__t.xml │ │ ├── structml__set__t.xml │ │ ├── structml__slice__node__t.xml │ │ ├── structml__slice__t.xml │ │ ├── structml__source__t.xml │ │ ├── structml__state__t.xml │ │ ├── structml__string__t.xml │ │ ├── structml__stringbuffer__node__t.xml │ │ ├── structml__stringbuffer__t.xml │ │ ├── structml__symbol__interval__t.xml │ │ ├── structml__symbol__t.xml │ │ ├── structml__term__t.xml │ │ ├── structml__tuple__t.xml │ │ ├── structml__type__t.xml │ │ ├── structml__uuid__t.xml │ │ ├── structml__value__t.xml │ │ ├── structml__visitor__t.xml │ │ ├── structmlc__block__expr__t.xml │ │ ├── structmlc__default__expr__t.xml │ │ ├── structmlc__define__t.xml │ │ ├── structmlc__expr__t.xml │ │ ├── structmlc__for__expr__t.xml │ │ ├── structmlc__frame__t.xml │ │ ├── structmlc__fun__expr__t.xml │ │ ├── structmlc__function__t.xml │ │ ├── structmlc__ident__expr__t.xml │ │ ├── structmlc__if__case__t.xml │ │ ├── structmlc__if__config__expr__t.xml │ │ ├── structmlc__if__expr__t.xml │ │ ├── structmlc__local__expr__t.xml │ │ ├── structmlc__local__t.xml │ │ ├── structmlc__param__t.xml │ │ ├── structmlc__parent__expr__t.xml │ │ ├── structmlc__parent__value__expr__t.xml │ │ ├── structmlc__string__expr__t.xml │ │ ├── structmlc__string__part__t.xml │ │ ├── structmlc__value__expr__t.xml │ │ ├── structstringmap__t.xml │ │ ├── structweakmap__t.xml │ │ ├── timelib__mem_8h.xml │ │ ├── unionml__inst__t.xml │ │ ├── weakmap_8h.xml │ │ ├── whereami_8h.xml │ │ └── xml.xsd ├── embedding.rst ├── extending.rst ├── index.rst ├── internals.rst ├── language.rst ├── library.rst ├── library │ ├── address.rst │ ├── any.rst │ ├── array.rst │ ├── ast.rst │ ├── base16.rst │ ├── base64.rst │ ├── boolean.rst │ ├── buffer.rst │ ├── bytecode.rst │ ├── cbor.rst │ ├── channel.rst │ ├── compiler.rst │ ├── condition.rst │ ├── context.rst │ ├── debugger.rst │ ├── enum.rst │ ├── error.rst │ ├── external.rst │ ├── file.rst │ ├── flags.rst │ ├── function.rst │ ├── general.rst │ ├── hierarchy.rst │ ├── interval.rst │ ├── json.rst │ ├── library.rst │ ├── list.rst │ ├── logging.rst │ ├── macro.rst │ ├── map.rst │ ├── math.rst │ ├── memory.rst │ ├── method.rst │ ├── minijs.rst │ ├── minilang.rst │ ├── mmap.rst │ ├── module.rst │ ├── number.rst │ ├── object.rst │ ├── polynomial.rst │ ├── pqueue.rst │ ├── range.rst │ ├── runtime.rst │ ├── rwlock.rst │ ├── semaphore.rst │ ├── sequence.rst │ ├── set.rst │ ├── slice.rst │ ├── socket.rst │ ├── stream.rst │ ├── string.rst │ ├── symbol.rst │ ├── table.rst │ ├── tasks.rst │ ├── thread.rst │ ├── time.rst │ ├── tuple.rst │ ├── type.rst │ ├── uuid.rst │ ├── xe.rst │ └── xml.rst ├── requirements.txt ├── start.rst ├── topics.rst ├── topics │ ├── arrays.rst │ ├── classes.rst │ ├── conditionals.rst │ ├── contexts.rst │ ├── errors.rst │ ├── functions.rst │ ├── guards.rst │ ├── loops.rst │ ├── macros.rst │ ├── methods.rst │ ├── modules.rst │ ├── must.rst │ ├── references.rst │ ├── scheduler.rst │ ├── sequences.rst │ ├── switch.rst │ └── types.rst ├── tutorial.rst └── tutorial │ └── 01_basics.rst ├── editor.mini ├── sed.txt ├── spec └── minilang.lang └── src ├── array ├── compare_cmp.c ├── compare_eq.c ├── compare_ge.c ├── compare_gt.c ├── compare_impl.h ├── compare_impl_complex.h ├── compare_impl_real.h ├── compare_le.c ├── compare_lt.c ├── compare_ne.c ├── update_add.c ├── update_and.c ├── update_div.c ├── update_impl.h ├── update_impl_complex.h ├── update_impl_integer.h ├── update_impl_real.h ├── update_max.c ├── update_min.c ├── update_mul.c ├── update_or.c ├── update_set.c ├── update_sub.c └── update_xor.c ├── ast.mini ├── build.rabs ├── coro.c ├── coro.h ├── document.mini ├── dynasm ├── dasm_arm.h ├── dasm_arm.lua ├── dasm_mips.h ├── dasm_mips.lua ├── dasm_ppc.h ├── dasm_ppc.lua ├── dasm_proto.h ├── dasm_x64.lua ├── dasm_x86.h ├── dasm_x86.lua └── dynasm.lua ├── exports.lst ├── extract_docs.mini ├── inthash.c ├── inthash.h ├── inthash_x64.s ├── keywords.c ├── keywords.lst ├── keywords.sh ├── linenoise.c ├── linenoise.h ├── miniconsole ├── minidbg ├── minilang.c ├── minilang.h ├── minilang.html ├── mininotebook ├── minipp.c ├── miniwasm.c ├── ml_array.c ├── ml_array.h ├── ml_ast.c ├── ml_ast.h ├── ml_ast_types.c ├── ml_base16.c ├── ml_base16.h ├── ml_base64.c ├── ml_base64.h ├── ml_boolean.c ├── ml_bytecode.c ├── ml_bytecode.h ├── ml_bytecode_jit.h ├── ml_bytecode_x64.dasc ├── ml_cbor.c ├── ml_cbor.h ├── ml_compiler.c ├── ml_compiler.h ├── ml_compiler2.h ├── ml_console.c ├── ml_console.h ├── ml_coroutine.c ├── ml_coroutine.h ├── ml_debugger.c ├── ml_debugger.h ├── ml_expr_types.c ├── ml_expr_types.h ├── ml_file.c ├── ml_file.h ├── ml_function.c ├── ml_json.c ├── ml_json.h ├── ml_library.c ├── ml_library.h ├── ml_list.c ├── ml_logging.c ├── ml_logging.h ├── ml_macros.h ├── ml_map.c ├── ml_math.c ├── ml_math.h ├── ml_method.c ├── ml_method.h ├── ml_minijs.c ├── ml_minijs.h ├── ml_mmap.c ├── ml_mmap.h ├── ml_module.c ├── ml_module.h ├── ml_number.c ├── ml_object.c ├── ml_object.h ├── ml_opcodes.c ├── ml_opcodes.h ├── ml_polynomial.c ├── ml_polynomial.h ├── ml_pqueue.c ├── ml_pqueue.h ├── ml_runtime.c ├── ml_runtime.h ├── ml_sequence.c ├── ml_sequence.h ├── ml_set.c ├── ml_slice.c ├── ml_socket.c ├── ml_socket.h ├── ml_stream.c ├── ml_stream.h ├── ml_string.c ├── ml_table.c ├── ml_table.h ├── ml_tasks.c ├── ml_tasks.h ├── ml_thread.c ├── ml_thread.h ├── ml_time.c ├── ml_time.h ├── ml_tuple.c ├── ml_types.c ├── ml_types.h ├── ml_uuid.c ├── ml_uuid.h ├── ml_xe.c ├── ml_xe.h ├── ml_xml.c ├── ml_xml.h ├── opcodes.mini ├── opcodes.txt ├── sha256.c ├── sha256.h ├── stringmap.c ├── stringmap.h ├── test ├── build.rabs ├── cbor_test1.mini ├── cbor_test1.out ├── example1.c ├── example1.mini ├── libuv_test1.mini ├── libuv_test2.mini ├── libuv_test3.mini ├── libuv_test4.mini ├── libuv_test5.mini ├── libuv_test6.mini ├── parser_test.mini ├── speed_test.mini ├── speed_test2.mini ├── test1.mini ├── test1.out ├── test1.pp ├── test10.mini ├── test10.out ├── test11.mini ├── test11.out ├── test12.mini ├── test12.out ├── test13.mini ├── test13.out ├── test14.mini ├── test14.out ├── test15.mini ├── test15.out ├── test16.mini ├── test16.out ├── test17.mini ├── test17.out ├── test18.mini ├── test18.out ├── test19.mini ├── test19.out ├── test2.mini ├── test2.out ├── test2.pp ├── test20.mini ├── test20.out ├── test21.mini ├── test21.out ├── test22.mini ├── test22.out ├── test23.mini ├── test23.out ├── test24.mini ├── test24.out ├── test25.mini ├── test25.out ├── test26.mini ├── test26.out ├── test27.mini ├── test27.out ├── test28.mini ├── test28.out ├── test3.mini ├── test3.out ├── test4.mini ├── test4.out ├── test5.mini ├── test5.out ├── test6.mini ├── test6.out ├── test7.mini ├── test7.out ├── test8.mini ├── test8.out ├── test9.mini ├── test9.out ├── test_gir1.mini └── test_gir2.mini ├── timelib_mem.h ├── tre.patch ├── weakmap.c ├── weakmap.h ├── whereami.c └── whereami.h /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | name: "CodeQL" 7 | 8 | on: 9 | push: 10 | branches: [master] 11 | pull_request: 12 | # The branches below must be a subset of the branches above 13 | branches: [master] 14 | schedule: 15 | - cron: '0 18 * * 4' 16 | 17 | jobs: 18 | analyze: 19 | name: Analyze 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | # Override automatic language detection by changing the below list 26 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 27 | language: ['cpp'] 28 | # Learn more... 29 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v2 34 | with: 35 | # We must fetch at least the immediate parents so that if this is 36 | # a pull request then we can checkout the head. 37 | fetch-depth: 2 38 | 39 | # If this run was triggered by a pull request event, then checkout 40 | # the head of the pull request instead of the merge commit. 41 | - run: git checkout HEAD^2 42 | if: ${{ github.event_name == 'pull_request' }} 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # ℹ️ Command-line programs to run using the OS shell. 55 | # 📚 https://git.io/JvXDl 56 | 57 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 58 | # and modify them (or add more) to build your code if your project 59 | # uses a compiled language 60 | 61 | - name: Install dependencies 62 | run: sudo apt-get install libgc-dev 63 | 64 | - name: Build 65 | run: make 66 | 67 | - name: Perform CodeQL Analysis 68 | uses: github/codeql-action/analyze@v1 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.obj 3 | *.lib 4 | *.a 5 | *.dll 6 | *.so 7 | *.so.* 8 | *.dylib 9 | *.exe 10 | /minilang 11 | /minipp 12 | /build.rabs.db/ 13 | /minicbor/ 14 | /radb/ 15 | /mpc/ 16 | /.settings/ 17 | /.cproject 18 | /.project 19 | /obj*/ 20 | /bin/ 21 | /lib/ 22 | /tmp/ 23 | .vscode/ 24 | .pydevproject 25 | .cquery 26 | /test/ 27 | docs/_util/__pycache__ 28 | docs/_build 29 | /html/ 30 | .ipynb_checkpoints 31 | callgrind.* 32 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/tre"] 2 | path = src/tre 3 | url = https://github.com/wrapl/tre.git 4 | [submodule "src/timelib"] 5 | path = src/timelib 6 | url = https://github.com/derickr/timelib.git 7 | [submodule "src/minicbor"] 8 | path = src/minicbor 9 | url = https://github.com/rajamukherji/minicbor.git 10 | [submodule "src/libbacktrace"] 11 | path = src/libbacktrace 12 | url = https://github.com/ianlancetaylor/libbacktrace.git 13 | [submodule "src/gc"] 14 | path = src/gc 15 | url = https://github.com/ivmai/bdwgc.git 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 wrapl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build.rabs: -------------------------------------------------------------------------------- 1 | :< ROOT >: 2 | 3 | %include common.rabs 4 | 5 | BIN_DIR := old or file("bin"):mkdir 6 | LIB_DIR := old or file("lib"):mkdir 7 | DOCS_DIR := old or file("docs"):mkdir 8 | 9 | let BuildDir := 'obj-{PLATFORM:lower}' 10 | 11 | vmount(BuildDir, "src") 12 | subdir(BuildDir) -------------------------------------------------------------------------------- /builddocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./bin/minilang src/extract_docs.mini docs.xml src/*.c 4 | ./bin/minilang src/document.mini docs/library src/*.c 5 | doxygen 6 | ./bin/minilang docgroups.mini 7 | cd docs && sphinx-build . ../html/ && cd .. 8 | echo `date` > html/reload 9 | -------------------------------------------------------------------------------- /docgroups.mini: -------------------------------------------------------------------------------- 1 | let Groups := set() 2 | for Header in dir("src") ->? _:ends(".h") do 3 | let File := file('src/{Header}', "r") 4 | for Line in seq File:read do 5 | if let Match := Line % r"/// \\defgroup (.*)\n" then 6 | Groups:insert(Match[2]) 7 | end 8 | end 9 | File:close 10 | end 11 | 12 | for Group in Groups do 13 | let File := file('docs/api/{Group}.rst', "w") 14 | File:write(Group:title, "\n") 15 | File:write(Group:length * "=", "\n") 16 | File:write("\n") 17 | File:write('.. doxygengroup:: {Group}\n') 18 | File:write(' :members:\n') 19 | File:close 20 | end 21 | -------------------------------------------------------------------------------- /docs/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | formats: [] 3 | build: 4 | os: ubuntu-22.04 5 | tools: 6 | python: "3.10" 7 | apt_packages: 8 | - graphviz 9 | 10 | python: 11 | install: 12 | - requirements: docs/requirements.txt 13 | sphinx: 14 | builder: html 15 | configuration: docs/conf.py 16 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/_static/js/minilang.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrapl/minilang/6bb4d0cc185f9c1af70046f63770779a0195f132/docs/_static/js/minilang.wasm -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. toctree:: 5 | :glob: 6 | :maxdepth: 1 7 | 8 | /api/* -------------------------------------------------------------------------------- /docs/api/booleans.rst: -------------------------------------------------------------------------------- 1 | Booleans 2 | ======== 3 | 4 | .. doxygengroup:: booleans 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/cbor.rst: -------------------------------------------------------------------------------- 1 | Cbor 2 | ==== 3 | 4 | .. doxygengroup:: cbor 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/compiler.rst: -------------------------------------------------------------------------------- 1 | Compiler 2 | ======== 3 | 4 | .. doxygengroup:: compiler 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/enums.rst: -------------------------------------------------------------------------------- 1 | Enums 2 | ===== 3 | 4 | .. doxygengroup:: enums 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/externals.rst: -------------------------------------------------------------------------------- 1 | Externals 2 | ========= 3 | 4 | .. doxygengroup:: externals 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/flags.rst: -------------------------------------------------------------------------------- 1 | Flags 2 | ===== 3 | 4 | .. doxygengroup:: flags 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/functions.rst: -------------------------------------------------------------------------------- 1 | Functions 2 | ========= 3 | 4 | .. doxygengroup:: functions 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/init.rst: -------------------------------------------------------------------------------- 1 | Init 2 | ==== 3 | 4 | .. doxygengroup:: init 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/inthash.rst: -------------------------------------------------------------------------------- 1 | Inthash 2 | ======= 3 | 4 | .. doxygengroup:: inthash 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/iterators.rst: -------------------------------------------------------------------------------- 1 | Iterators 2 | ========= 3 | 4 | .. doxygengroup:: iterators 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/lists.rst: -------------------------------------------------------------------------------- 1 | Lists 2 | ===== 3 | 4 | .. doxygengroup:: lists 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/logging.rst: -------------------------------------------------------------------------------- 1 | Logging 2 | ======= 3 | 4 | .. doxygengroup:: logging 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/maps.rst: -------------------------------------------------------------------------------- 1 | Maps 2 | ==== 3 | 4 | .. doxygengroup:: maps 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/math.rst: -------------------------------------------------------------------------------- 1 | Math 2 | ==== 3 | 4 | .. doxygengroup:: math 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/methods.rst: -------------------------------------------------------------------------------- 1 | Methods 2 | ======= 3 | 4 | .. doxygengroup:: methods 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/modules.rst: -------------------------------------------------------------------------------- 1 | Modules 2 | ======= 3 | 4 | .. doxygengroup:: modules 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/names.rst: -------------------------------------------------------------------------------- 1 | Names 2 | ===== 3 | 4 | .. doxygengroup:: names 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/numbers.rst: -------------------------------------------------------------------------------- 1 | Numbers 2 | ======= 3 | 4 | .. doxygengroup:: numbers 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/objects.rst: -------------------------------------------------------------------------------- 1 | Objects 2 | ======= 3 | 4 | .. doxygengroup:: objects 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/runtime.rst: -------------------------------------------------------------------------------- 1 | Runtime 2 | ======= 3 | 4 | .. doxygengroup:: runtime 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/sets.rst: -------------------------------------------------------------------------------- 1 | Sets 2 | ==== 3 | 4 | .. doxygengroup:: sets 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/slices.rst: -------------------------------------------------------------------------------- 1 | Slices 2 | ====== 3 | 4 | .. doxygengroup:: slices 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/streams.rst: -------------------------------------------------------------------------------- 1 | Streams 2 | ======= 3 | 4 | .. doxygengroup:: streams 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/stringmap.rst: -------------------------------------------------------------------------------- 1 | Stringmap 2 | ========= 3 | 4 | .. doxygengroup:: stringmap 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/strings.rst: -------------------------------------------------------------------------------- 1 | Strings 2 | ======= 3 | 4 | .. doxygengroup:: strings 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/symbols.rst: -------------------------------------------------------------------------------- 1 | Symbols 2 | ======= 3 | 4 | .. doxygengroup:: symbols 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/tuples.rst: -------------------------------------------------------------------------------- 1 | Tuples 2 | ====== 3 | 4 | .. doxygengroup:: tuples 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/api/types.rst: -------------------------------------------------------------------------------- 1 | Types 2 | ===== 3 | 4 | .. doxygengroup:: types 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/docutils.conf: -------------------------------------------------------------------------------- 1 | [restructuredtext parser] 2 | syntax_highlight = short 3 | tab_width = 4 4 | smart_quotes = no -------------------------------------------------------------------------------- /docs/doxygen/xml/combine.xslt: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/doxygen/xml/dap_8h.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dap.h 5 | 6 | 7 | 8 | 9 | 10 | #ifndefDAP_H 11 | #defineDAP_H 12 | 13 | #endif 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/doxygen/xml/group__init.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | init 5 | Init 6 | 7 | 8 | void 9 | void ml_types_init 10 | (stringmap_t *Globals) 11 | ml_types_init 12 | 13 | stringmap_t * 14 | Globals 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/doxygen/xml/index.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /docs/doxygen/xml/ml__set_8h.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ml_set.h 5 | 6 | 7 | void 8 | void ml_set_init 9 | () 10 | ml_set_init 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | #ifndefML_SET_H 26 | #defineML_SET_H 27 | 28 | voidml_set_init(); 29 | 30 | #endif 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structcoro__stack.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | coro_stack 5 | 6 | 7 | void * 8 | void* sptr 9 | 10 | sptr 11 | coro_stack::sptr 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | size_t 22 | size_t ssze 23 | 24 | ssze 25 | coro_stack::ssze 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | coro_stacksptr 42 | coro_stackssze 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structinthash2__node__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | inthash2_node_t 5 | 6 | 7 | uintptr_t 8 | uintptr_t Key 9 | 10 | Key 11 | inthash2_node_t::Key 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | size_t 22 | size_t Offset 23 | 24 | Offset 25 | inthash2_node_t::Offset 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | inthash2_node_tKey 42 | inthash2_node_tOffset 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structinthash2__result__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | inthash2_result_t 5 | 6 | 7 | void * 8 | void* Value 9 | 10 | Value 11 | inthash2_result_t::Value 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | int 22 | int Present 23 | 24 | Present 25 | inthash2_result_t::Present 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | inthash2_result_tPresent 42 | inthash2_result_tValue 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structinthash__result__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | inthash_result_t 5 | 6 | 7 | void * 8 | void* Value 9 | 10 | Value 11 | inthash_result_t::Value 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | int 22 | int Present 23 | 24 | Present 25 | inthash_result_t::Present 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | inthash_result_tPresent 42 | inthash_result_tValue 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structlinenoiseCompletions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | linenoiseCompletions 5 | 6 | 7 | size_t 8 | size_t len 9 | 10 | len 11 | linenoiseCompletions::len 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | char ** 22 | char** cvec 23 | 24 | cvec 25 | linenoiseCompletions::cvec 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | linenoiseCompletionscvec 42 | linenoiseCompletionslen 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structml__factor__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ml_factor_t 5 | 6 | 7 | int 8 | int Variable 9 | 10 | Variable 11 | ml_factor_t::Variable 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | int 22 | int Degree 23 | 24 | Degree 25 | ml_factor_t::Degree 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ml_factor_tDegree 42 | ml_factor_tVariable 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structml__source__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ml_source_t 5 | 6 | 7 | const char * 8 | const char* Name 9 | 10 | Name 11 | ml_source_t::Name 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | int 22 | int Line 23 | 24 | Line 25 | ml_source_t::Line 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ml_source_tLine 42 | ml_source_tName 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structml__stringbuffer__node__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ml_stringbuffer_node_t 5 | 6 | 7 | ml_stringbuffer_node_t * 8 | ml_stringbuffer_node_t* Next 9 | 10 | Next 11 | ml_stringbuffer_node_t::Next 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | char 22 | char Chars[ML_STRINGBUFFER_NODE_SIZE] 23 | [ML_STRINGBUFFER_NODE_SIZE] 24 | Chars 25 | ml_stringbuffer_node_t::Chars 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Next 45 | 46 | 47 | 48 | 49 | 50 | ml_stringbuffer_node_tChars 51 | ml_stringbuffer_node_tNext 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structml__value__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ml_value_t 5 | 6 | 7 | ml_type_t * 8 | ml_type_t* Type 9 | 10 | Type 11 | ml_value_t::Type 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Type 35 | 36 | 37 | Constructor 38 | deref 39 | 40 | 41 | Parents 42 | TypedFns 43 | 44 | 45 | Exports 46 | 47 | 48 | 49 | 50 | 51 | 52 | Type 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | ml_value_tType 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structmlc__ident__expr__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mlc_ident_expr_t 5 | 6 | 7 | const char * 8 | const char* Ident 9 | 10 | Ident 11 | mlc_ident_expr_t::Ident 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | MLC_EXPR_FIELDS 25 | (ident) 26 | MLC_EXPR_FIELDS 27 | mlc_ident_expr_t::MLC_EXPR_FIELDS 28 | 29 | ident 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | mlc_ident_expr_tIdent 47 | mlc_ident_expr_tMLC_EXPR_FIELDS 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/doxygen/xml/structstringmap__t.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | stringmap_t 5 | 6 | 7 | stringmap_node_t * 8 | stringmap_node_t* Root 9 | 10 | Root 11 | stringmap_t::Root 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | int 22 | int Size 23 | 24 | Size 25 | stringmap_t::Size 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | stringmap_tRoot 42 | stringmap_tSize 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/doxygen/xml/xml.xsd: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/extending.rst: -------------------------------------------------------------------------------- 1 | Extending 2 | ========= -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Minilang 2 | ======== 3 | 4 | Introduction 5 | ------------ 6 | 7 | *Minilang* is a small imperative language, designed to be embedded into programs 8 | written in *C*. Although initially developed for *Rabs* ``_ to specify build functions and dependencies, it has evolved into a comprehensive embeddable scripting language. It has the following goals / features: 9 | 10 | **Minimal dependencies** 11 | *Minilang* has no mandatory dependencies other than the Hans Boehm garbage 12 | collector and standard *C* libraries. 13 | 14 | **Minimal language** 15 | *Minilang* is a fairly simple language with no syntax for classes, modules, etc. This allows it to be embedded in applications with strict control on available features. There is no loss in expression though as the syntax allows classes and modules to be added seamlessly. 16 | 17 | **Expression based** 18 | Other than declarations, everything else in *Minilang* is an expression, avoiding the need for temporary variables for intermediate values resulting in concise code. Of course, variables can be defined for clarity as required. 19 | 20 | **One-shot Continuations** 21 | All function calls in *Minilang* are implemented using one-shot continuations. This allows asynchronous functions and preemptive multitasking to be added if required, without imposing them when they are not needed. 22 | 23 | **Flexible API** 24 | The *Minilang* compiler API uses callbacks where possible giving applications complete flexibility on how to use *Minilang*. 25 | 26 | **Easy to embed & extend** 27 | *Minilang* provides a comprehensive embedding API to support a wider range of use cases. It is easy to create new functions in *C* to use in *Minilang*. 28 | 29 | **Full closures** 30 | Functions in *Minilang* automatically capture their environment, creating 31 | closures at runtime. Closures can be passed around as first-class values. 32 | 33 | 34 | Sample 35 | ------ 36 | 37 | .. code-block:: mini 38 | :linenos: 39 | 40 | print("Hello world!\n") 41 | 42 | var L := [1, 2, 3, 4, 5] 43 | 44 | for X in L do 45 | print('X = {X}\n') 46 | end 47 | 48 | Details 49 | ======= 50 | 51 | .. toctree:: 52 | :hidden: 53 | :maxdepth: 2 54 | 55 | /start 56 | /language 57 | /tutorial 58 | /topics 59 | /library 60 | /embedding 61 | /extending 62 | /api 63 | /internals 64 | -------------------------------------------------------------------------------- /docs/library.rst: -------------------------------------------------------------------------------- 1 | Library 2 | ======= 3 | 4 | .. toctree:: 5 | :glob: 6 | :maxdepth: 1 7 | 8 | /library/* -------------------------------------------------------------------------------- /docs/library/any.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | any 8 | === 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type any` 13 | Base type for all values. 14 | 15 | 16 | :mini:`meth (Value₁: any) != (Value₂: any): Value₂ | nil` 17 | Returns :mini:`Value₂` if :mini:`Value₁` and :mini:`Value₂` are not exactly the same instance and :mini:`nil` otherwise. 18 | 19 | 20 | :mini:`meth (Arg₁: any) != (Arg₂: any, Arg₃: any, ...): any | nil` 21 | Returns :mini:`Argₙ` if :mini:`Arg₁ != Argᵢ` for i = 2, ..., n and :mini:`nil` otherwise. 22 | 23 | 24 | :mini:`meth #(Value: any): integer` 25 | Returns a hash for :mini:`Value` for use in lookup tables, etc. 26 | 27 | 28 | :mini:`meth (Arg₁: any) < (Arg₂: any, Arg₃: any, ...): any | nil` 29 | Returns :mini:`Argₙ` if :mini:`Arg₁ < Arg₂ < ... < Argₙ` and :mini:`nil` otherwise. 30 | 31 | 32 | :mini:`meth (Arg₁: any) <= (Arg₂: any, Arg₃: any, ...): any | nil` 33 | Returns :mini:`Argₙ` if :mini:`Arg₁ <= Arg₂ <= ... <= Argₙ` and :mini:`nil` otherwise. 34 | 35 | 36 | :mini:`meth (Value₁: any) <> (Value₂: any): integer` 37 | Compares :mini:`Value₁` and :mini:`Value₂` and returns :mini:`-1`, :mini:`0` or :mini:`1`. 38 | This comparison is based on the types and internal addresses of :mini:`Value₁` and :mini:`Value₂` and thus only has no persistent meaning. 39 | 40 | 41 | :mini:`meth (Value₁: any) = (Value₂: any): Value₂ | nil` 42 | Returns :mini:`Value₂` if :mini:`Value₁` and :mini:`Value₂` are exactly the same instance and :mini:`nil` otherwise. 43 | 44 | 45 | :mini:`meth (Arg₁: any) = (Arg₂: any, Arg₃: any, ...): any | nil` 46 | Returns :mini:`Argₙ` if :mini:`Arg₁ = Arg₂ = ... = Argₙ` and :mini:`nil` otherwise. 47 | 48 | 49 | :mini:`meth (Arg₁: any) > (Arg₂: any, Arg₃: any, ...): any | nil` 50 | Returns :mini:`Argₙ` if :mini:`Arg₁ > Arg₂ > ... > Argₙ` and :mini:`nil` otherwise. 51 | 52 | 53 | :mini:`meth (Arg₁: any) >= (Arg₂: any, Arg₃: any, ...): any | nil` 54 | Returns :mini:`Argₙ` if :mini:`Arg₁ >= Arg₂ >= ... >= Argₙ` and :mini:`nil` otherwise. 55 | 56 | 57 | :mini:`meth (Value: any):in(Type: type): Value | nil` 58 | Returns :mini:`Value` if it is an instance of :mini:`Type` or a type that inherits from :mini:`Type` and :mini:`nil` otherwise. 59 | 60 | 61 | :mini:`meth (A: any):max(B: any): any` 62 | Returns :mini:`A` if :mini:`A > B` and :mini:`B` otherwise. 63 | 64 | 65 | :mini:`meth (A: any):min(B: any): any` 66 | Returns :mini:`A` if :mini:`A < B` and :mini:`B` otherwise. 67 | 68 | 69 | :mini:`meth (Buffer: string::buffer):append(Value: any)` 70 | Appends a representation of :mini:`Value` to :mini:`Buffer`. 71 | 72 | 73 | -------------------------------------------------------------------------------- /docs/library/base16.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | base16 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun base16::decode(String: address): address` 13 | *TBD* 14 | 15 | 16 | :mini:`fun base16::encode(Address: address): string` 17 | *TBD* 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/library/base64.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | base64 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun base64::decode(String: address): address` 13 | *TBD* 14 | 15 | 16 | :mini:`fun base64::encode(Address: address): string` 17 | *TBD* 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/library/bytecode.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | bytecode 8 | ======== 9 | 10 | .. rst-class:: mini-api 11 | 12 | This is a mostly internal module, subject to change. 13 | 14 | :mini:`type closure < function, sequence` 15 | A Minilang function. 16 | 17 | 18 | :mini:`fun closure(Original: closure): closure` 19 | Returns a copy of :mini:`Closure`. 20 | 21 | 22 | :mini:`meth (Closure: closure):info: map` 23 | Returns some information about :mini:`Closure`. 24 | 25 | 26 | :mini:`meth (Closure: closure):list: string` 27 | Returns a listing of the bytecode of :mini:`Closure`. 28 | 29 | 30 | :mini:`meth (Closure: closure):parameters: list` 31 | Returns the list of parameter names of :mini:`Closure`. 32 | 33 | 34 | :mini:`meth (Closure: closure):values: map` 35 | Returns some information about :mini:`Closure`. 36 | 37 | 38 | :mini:`meth (Buffer: string::buffer):append(Closure: closure)` 39 | Appends a representation of :mini:`Closure` to :mini:`Buffer`. 40 | 41 | 42 | :mini:`type closure::info` 43 | Information about a closure. 44 | 45 | 46 | :mini:`type continuation < state, sequence` 47 | A bytecode function frame which can be resumed. 48 | 49 | 50 | :mini:`type variable` 51 | A variable, which can hold another value (returned when dereferenced) and assigned a new value. 52 | Variables may optionally be typed, assigning a value that is not an instance of the specified type (or a subtype) will raise an error. 53 | 54 | 55 | :mini:`meth variable(Value: any): variable` 56 | Return a new untyped variable with current value :mini:`Value`. 57 | 58 | 59 | :mini:`meth variable(Value: any, Type: type): variable` 60 | Return a new typed variable with type :mini:`Type` and current value :mini:`Value`. 61 | 62 | 63 | :mini:`meth variable(): variable` 64 | Return a new untyped variable with current value :mini:`nil`. 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/library/channel.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | channel 8 | ======= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun channel()` 13 | *TBD* 14 | 15 | 16 | :mini:`type channel` 17 | *TBD* 18 | 19 | 20 | :mini:`meth (Channel: channel):close(Function: function, ...)` 21 | *TBD* 22 | 23 | 24 | :mini:`meth (Channel: channel):next: any` 25 | *TBD* 26 | 27 | 28 | :mini:`meth (Channel: channel):next(Reply: any): any` 29 | *TBD* 30 | 31 | 32 | :mini:`meth (Channel: channel):open: channel | nil` 33 | *TBD* 34 | 35 | 36 | :mini:`meth (Channel: channel):send(Message: any): any` 37 | *TBD* 38 | 39 | 40 | :mini:`meth (Channel: channel):start(Function: function, ...): any` 41 | *TBD* 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/library/condition.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | condition 8 | ========= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type condition` 13 | A condition for synchronizing concurrent code. 14 | 15 | 16 | :mini:`fun condition(): condition` 17 | Returns a new condition. 18 | 19 | 20 | :mini:`meth (Condition: condition):broadcast` 21 | Signals :mini:`Condition`, resuming all waiters. 22 | 23 | 24 | :mini:`meth (Condition: condition):signal` 25 | Signals :mini:`Condition`, resuming a single waiter. 26 | 27 | 28 | :mini:`meth (Condition: condition):wait(Semaphore: semaphore): integer` 29 | Increments :mini:`Semaphore`, waits until :mini:`Condition` is signalled, then decrements :mini:`Semaphore` (waiting if necessary) and returns its value. 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/library/context.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | context 8 | ======= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type context < function` 13 | A context key can be used to create context specific values. 14 | If :mini:`key` is a context key, then calling :mini:`key()` no arguments returns the value associated with the key in the current context, or :mini:`nil` is no value is associated. 15 | Calling :mini:`key(Value, Function)` will invoke :mini:`Function` in a new context where :mini:`key` is associated with :mini:`Value`. 16 | 17 | 18 | :mini:`fun context(): context` 19 | Creates a new context specific key. 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/library/debugger.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | debugger 8 | ======== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun debugger(Function: any): debugger` 13 | Returns a new debugger for :mini:`Function()`. 14 | 15 | 16 | :mini:`meth (Debugger: debugger):breakpoint_clear(Source: string, Line: integer)` 17 | Clears any breakpoints from :mini:`Source` at line :mini:`Line`. 18 | 19 | 20 | :mini:`meth (Debugger: debugger):breakpoint_set(Source: string, Line: integer)` 21 | Sets a breakpoint in :mini:`Source` at line :mini:`Line`. 22 | 23 | 24 | :mini:`meth (Debugger: debugger):continue(State: state, Value: any)` 25 | Resume :mini:`State` with :mini:`Value` in the debugger. 26 | 27 | 28 | :mini:`meth (Debugger: debugger):error_mode(Set: any)` 29 | If :mini:`Set` is not :mini:`nil` then :mini:`Debugger` will stop on errors. 30 | 31 | 32 | :mini:`meth (Debugger: debugger):step_in(State: state, Value: any)` 33 | Resume :mini:`State` with :mini:`Value` in the debugger, stopping after the next line. 34 | 35 | 36 | :mini:`meth (Debugger: debugger):step_mode(Set: any)` 37 | If :mini:`Set` is not :mini:`nil` then :mini:`Debugger` will stop on after each line. 38 | 39 | 40 | :mini:`meth (Debugger: debugger):step_out(State: state, Value: any)` 41 | Resume :mini:`State` with :mini:`Value` in the debugger, stopping at the end of the current function. 42 | 43 | 44 | :mini:`meth (Debugger: debugger):step_over(State: state, Value: any)` 45 | Resume :mini:`State` with :mini:`Value` in the debugger, stopping after the next line in the same function (i.e. stepping over function calls). 46 | 47 | 48 | :mini:`meth (State: state):locals: list[string]` 49 | Returns the list of locals in :mini:`State`. Returns an empty list if :mini:`State` does not have any debugging information. 50 | 51 | 52 | :mini:`meth (State: state):source: tuple[string, integer]` 53 | Returns the source location for :mini:`State`. 54 | 55 | 56 | :mini:`meth (State: state):trace: list[state]` 57 | Returns the call trace from :mini:`State`, excluding states that do not have debugging information. 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/library/error.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | error 8 | ===== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type error` 13 | An error. Values of this type are not accessible from Minilang code since they are caught by the runtime. Each error contains an *error value* which contains the details of the error. 14 | 15 | 16 | :mini:`fun error(Type: string, Message: string): error` 17 | Creates an error exception with type :mini:`Type` and message :mini:`Message`. Since this creates an exception, it will trigger the current exception handler. 18 | 19 | 20 | :mini:`type error::value` 21 | An error value. Error values contain the details of an error but are not themselves errors (since errors are caught by the runtime). 22 | 23 | 24 | :mini:`meth (Error: error::value):message: string` 25 | Returns the message of :mini:`Error`. 26 | 27 | 28 | :mini:`meth (Error: error::value):raise: error` 29 | Returns :mini:`Error` as an error (i.e. rethrows the error). 30 | 31 | 32 | :mini:`meth (Error: error::value):trace: list` 33 | Returns the stack trace of :mini:`Error` as a list of tuples. 34 | 35 | 36 | :mini:`meth (Error: error::value):type: string` 37 | Returns the type of :mini:`Error`. 38 | 39 | 40 | :mini:`fun raise(Type: string, Value: any): error` 41 | Creates a general exception with type :mini:`Type` and value :mini:`Value`. Since this creates an exception, it will trigger the current exception handler. 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/library/external.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | external 8 | ======== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type external` 13 | A placeholder value that can be encoded and replaced on decoding. 14 | 15 | 16 | :mini:`fun external(Name: string): external` 17 | *TBD* 18 | 19 | 20 | :mini:`fun external(Name: string): external` 21 | *TBD* 22 | 23 | 24 | :mini:`meth (External: external) :: (Import: string): external` 25 | *TBD* 26 | 27 | 28 | :mini:`type external::set` 29 | *TBD* 30 | 31 | 32 | :mini:`meth external::set(): external::set` 33 | *TBD* 34 | 35 | 36 | :mini:`meth (Externals: external::set):add(Name: string, Value: any)` 37 | *TBD* 38 | 39 | 40 | :mini:`fun external::add(Name: string, Value: any)` 41 | *TBD* 42 | 43 | 44 | :mini:`fun external::get(Name: string): any | error` 45 | *TBD* 46 | 47 | 48 | -------------------------------------------------------------------------------- /docs/library/file.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | file 8 | ==== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type dir < sequence` 13 | *TBD* 14 | 15 | 16 | :mini:`fun dir(Path: string): dir` 17 | *TBD* 18 | 19 | 20 | :mini:`meth (Dir: dir):read: string` 21 | *TBD* 22 | 23 | 24 | :mini:`type file < stream` 25 | A file handle for reading / writing. 26 | 27 | 28 | :mini:`fun file(Path: string, Mode: string): file` 29 | Opens the file at :mini:`Path` depending on :mini:`Mode`, 30 | 31 | * :mini:`"r"`: opens the file for reading, 32 | * :mini:`"w"`: opens the file for writing, 33 | * :mini:`"a"`: opens the file for appending. 34 | 35 | 36 | :mini:`meth (File: file):close` 37 | Closes :mini:`File`. 38 | 39 | 40 | :mini:`meth (File: file):eof: File | nil` 41 | Returns :mini:`File` if :mini:`File` is closed, otherwise return :mini:`nil`. 42 | 43 | 44 | :mini:`meth (File: file):flush` 45 | Flushes any pending writes to :mini:`File`. 46 | 47 | 48 | :mini:`type file::mode < enum` 49 | * :mini:`::DIR` 50 | * :mini:`::CHR` 51 | * :mini:`::BLK` 52 | * :mini:`::REG` 53 | * :mini:`::LNK` 54 | * :mini:`::SOCK` 55 | * :mini:`::FIFO` 56 | 57 | 58 | :mini:`type file::stat` 59 | *TBD* 60 | 61 | 62 | :mini:`fun file::stat(Path: string): file::stat` 63 | *TBD* 64 | 65 | 66 | :mini:`meth (Arg₁: file::stat):atime` 67 | *TBD* 68 | 69 | 70 | :mini:`meth (Arg₁: file::stat):ctime` 71 | *TBD* 72 | 73 | 74 | :mini:`meth (Arg₁: file::stat):mode` 75 | *TBD* 76 | 77 | 78 | :mini:`meth (Arg₁: file::stat):mtime` 79 | *TBD* 80 | 81 | 82 | :mini:`meth (Arg₁: file::stat):size` 83 | *TBD* 84 | 85 | 86 | :mini:`type popen < file` 87 | A file that reads or writes to a running subprocess. 88 | 89 | 90 | :mini:`fun popen(Command: string, Mode: string): popen` 91 | Executes :mini:`Command` with the shell and returns an open file to communicate with the subprocess depending on :mini:`Mode`, 92 | 93 | * :mini:`"r"`: opens the file for reading, 94 | * :mini:`"w"`: opens the file for writing. 95 | 96 | 97 | :mini:`meth (File: popen):close: integer` 98 | Waits for the subprocess to finish and returns the exit status. 99 | 100 | 101 | :mini:`fun dir::create(Path: string, Mode: integer)` 102 | *TBD* 103 | 104 | 105 | :mini:`fun dir::remove(Path: string)` 106 | *TBD* 107 | 108 | 109 | :mini:`fun file::exists(Path: string): string | nil` 110 | *TBD* 111 | 112 | 113 | :mini:`fun file::rename(Old: string, New: string)` 114 | Renames the file :mini:`Old` to :mini:`New`. 115 | 116 | 117 | :mini:`fun file::unlink(Path: string)` 118 | Removes the file at :mini:`Path`. 119 | 120 | 121 | -------------------------------------------------------------------------------- /docs/library/json.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | json 8 | ==== 9 | 10 | .. rst-class:: mini-api 11 | 12 | JSON values are mapped to Minilang as follows: 13 | 14 | * :json:`null` |harr| :mini:`nil` 15 | * :json:`true` |harr| :mini:`true` 16 | * :json:`false` |harr| :mini:`false` 17 | * *integer* |harr| :mini:`integer` 18 | * *real* |harr| :mini:`real` 19 | * *string* |harr| :mini:`string` 20 | * *array* |harr| :mini:`list` 21 | * *object* |harr| :mini:`map` 22 | 23 | :mini:`meth json::decode(Json: address): any` 24 | Decodes :mini:`Json` into a Minilang value. 25 | 26 | 27 | :mini:`meth json::encode(Value: any): string | error` 28 | Encodes :mini:`Value` into JSON, raising an error if :mini:`Value` cannot be represented as JSON. 29 | 30 | 31 | :mini:`type json < string` 32 | Contains a JSON encoded value. Primarily used to distinguish strings containing JSON from other strings (e.g. for CBOR encoding). 33 | 34 | 35 | :mini:`fun json(Value: any): json` 36 | Encodes :mini:`Value` into JSON. 37 | 38 | 39 | :mini:`meth (Json: json):decode: any | error` 40 | Decodes the JSON string in :mini:`Json` into a Minilang value. 41 | 42 | 43 | :mini:`meth (Json: json):value: any | error` 44 | Decodes the JSON string in :mini:`Json` into a Minilang value. 45 | 46 | 47 | :mini:`type json::decoder < stream` 48 | A JSON decoder that can be written to as a stream and calls a user-supplied callback whenever a complete value is decoded. 49 | 50 | 51 | :mini:`meth json::decoder(Callback: function): json::decoder` 52 | Returns a new JSON decoder that calls :mini:`Callback(Value)` whenever a complete JSON value is written to the decoder. 53 | 54 | 55 | :mini:`meth json::decoder(Skip: string, Callback: function): json::decoder` 56 | Returns a new JSON decoder that calls :mini:`Callback(Value)` whenever a complete JSON value is written to the decoder. 57 | 58 | 59 | :mini:`meth json::decode(Stream: stream): any` 60 | Decodes the content of :mini:`Json` into a Minilang value. 61 | 62 | 63 | :mini:`meth json::encode(Buffer: string::buffer, Value: any)` 64 | *TBD* 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/library/library.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | library 8 | ======= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun getpath()` 13 | *TBD* 14 | 15 | 16 | :mini:`type importer < function` 17 | *TBD* 18 | 19 | 20 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: importer)` 21 | *TBD* 22 | 23 | 24 | :mini:`type module::dir` 25 | *TBD* 26 | 27 | 28 | :mini:`meth (Arg₁: module::dir) :: (Arg₂: string)` 29 | *TBD* 30 | 31 | 32 | :mini:`fun addpath(Arg₁: string)` 33 | *TBD* 34 | 35 | 36 | :mini:`fun unload(Path: string): nil` 37 | *TBD* 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/library/logging.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | logging 8 | ======= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun logger::level(Level?: string): string` 13 | Gets or sets the logging level for default logging. Returns the log level. 14 | 15 | 16 | :mini:`type log::macro < function` 17 | *TBD* 18 | 19 | 20 | :mini:`type logger` 21 | A logger. 22 | 23 | 24 | :mini:`fun logger(Category: string): logger` 25 | Returns a new logger with levels :mini:`::error`, :mini:`::warn`, :mini:`::info` and :mini:`::debug`. 26 | 27 | 28 | :mini:`meth (Logger: logger) :: (Level: string): logger::fn` 29 | *TBD* 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/library/memory.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | memory 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun collect()` 13 | Call garbage collector. 14 | 15 | 16 | :mini:`fun dump()` 17 | *TBD* 18 | 19 | 20 | :mini:`fun usage()` 21 | *TBD* 22 | 23 | 24 | :mini:`fun address(Value: any): integer` 25 | Returns the internal address of :mini:`Value` as an integer. 26 | 27 | 28 | :mini:`fun size(Value: any): list[map]` 29 | Returns information about the blocks of memory referenced by :mini:`Value`. 30 | 31 | 32 | :mini:`fun trace(Value: any): list[map]` 33 | Returns information about the blocks of memory referenced by :mini:`Value`. 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/library/method.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | method 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun method::list(): list[method]` 13 | *TBD* 14 | 15 | 16 | :mini:`fun method::isolate(Args: any, ..., Fn: function): any` 17 | Evaluates :mini:`Fn(Args)` in a new method context and returns the result. 18 | 19 | 20 | :mini:`fun mlmethodisolated(Arg₁: any)` 21 | *TBD* 22 | 23 | 24 | :mini:`type method < function` 25 | A map of type signatures to functions. Each type signature consists of a number of types and a flag denoting whether the signature is variadic. 26 | 27 | :mini:`(M: method)(Arg₁, ..., Argₙ)` 28 | Calls :mini:`Fn(Arg₁, ..., Argₙ)` where :mini:`Fn` is the function associated with the closest matching type signature defined in :mini:`M`. 29 | 30 | A type signature :mini:`(Type₁, ..., Type/k, Variadic)` matches if :mini:`type(Argᵢ) < Typeᵢ` for each :math:`i = 1, ..., k` and either :math:`n = k` or :math:`n < k` and :math:`Variadic` is true. 31 | 32 | * A type signature is considered a closer match if its types are closer in terms of subtyping to the types of the arguments. 33 | * A type signature with the same number of types as arguments is considered a closer match than a matching variadic signature with fewer types. 34 | 35 | 36 | :mini:`meth method(): method` 37 | Returns a new anonymous method. 38 | 39 | 40 | :mini:`meth method(Name: string): method` 41 | Returns the method with name :mini:`Name`. 42 | 43 | 44 | :mini:`meth (Arg₁: method):MLMethodDefault(...)` 45 | *TBD* 46 | 47 | 48 | :mini:`meth (Arg₁: method)[...]` 49 | *TBD* 50 | 51 | 52 | :mini:`meth (Arg₁: method):list` 53 | *TBD* 54 | 55 | 56 | :mini:`meth method::define(Method: method, Types: type, ..., ..?: any, Function: function): Function` 57 | Adds a new type signature and associated function to :mini:`Method`. If the last argument is :mini:`..` then the signature is variadic. Method definitions using :mini:`meth` are translated into calls to :mini:`method::set`. 58 | 59 | 60 | :mini:`meth (Method: method):name: string` 61 | Returns the name of :mini:`Method`. 62 | 63 | 64 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: method)` 65 | *TBD* 66 | 67 | 68 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: method::anon)` 69 | *TBD* 70 | 71 | 72 | :mini:`type method::context` 73 | A context for isolating method definitions. 74 | 75 | :mini:`(C: method::context)(Args: any, ..., Fn: function): any` 76 | Calls :mini:`Fn(Args)` in a new context using :mini:`C` for method definitions. 77 | 78 | 79 | :mini:`fun method::context(): method::context` 80 | Returns a new context for method definitions. The new context will inherit methods definitions from the current context. 81 | 82 | 83 | :mini:`type method::isolated < function` 84 | *TBD* 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/library/minijs.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | minijs 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | Provides a specialized encoding of Minilang values to and from JSON with support for complex or cyclic data structures. 13 | 14 | * :json:`null` |harr| :mini:`nil` 15 | * :json:`true` |harr| :mini:`true` 16 | * :json:`false` |harr| :mini:`false` 17 | * *integer* |harr| :mini:`integer` 18 | * *real* |harr| :mini:`real` 19 | * *string* |harr| :mini:`string` 20 | * ``[type, ...]`` |harr| *other* 21 | 22 | :mini:`meth minijs::decode(Json: any): any | error` 23 | *TBD* 24 | 25 | 26 | :mini:`meth minijs::decode(Json: any, Externals: external::set): any | error` 27 | *TBD* 28 | 29 | 30 | :mini:`meth minijs::encode(Value: any): any` 31 | *TBD* 32 | 33 | 34 | :mini:`meth minijs::encode(Value: any, Externals: external::set): any` 35 | *TBD* 36 | 37 | 38 | :mini:`type minijs` 39 | *TBD* 40 | 41 | 42 | :mini:`fun minijs(Value: any): minijs` 43 | *TBD* 44 | 45 | 46 | :mini:`meth (Arg₁: minijs):value` 47 | *TBD* 48 | 49 | 50 | -------------------------------------------------------------------------------- /docs/library/minilang.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | minilang 8 | ======== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun clock()` 13 | *TBD* 14 | 15 | 16 | :mini:`fun halt(Code?: integer)` 17 | Causes the current process to exit with optional exit code :mini:`Code` or :mini:`0` if omitted. 18 | 19 | 20 | :mini:`fun locale(): string` 21 | *TBD* 22 | 23 | 24 | :mini:`fun now()` 25 | *TBD* 26 | 27 | 28 | :mini:`fun print(Values: any, ...): nil` 29 | Prints :mini:`Values` to standard output, converting to strings if necessary. 30 | 31 | 32 | :mini:`fun mlconsole(Arg₁: integer)` 33 | *TBD* 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/library/mmap.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | mmap 8 | ==== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type mmap < address` 13 | *TBD* 14 | 15 | 16 | :mini:`meth (Arg₁: mmap):unmap` 17 | *TBD* 18 | 19 | 20 | :mini:`type mmap::buffer < mmap, buffer` 21 | *TBD* 22 | 23 | 24 | :mini:`meth mmap(Arg₁: string, Arg₂: string)` 25 | *TBD* 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/library/module.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | module 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type module` 13 | *TBD* 14 | 15 | 16 | :mini:`meth (Module: module) :: (Name: string): any` 17 | Imports a symbol from a module. 18 | 19 | 20 | :mini:`meth (Arg₁: module):exports` 21 | *TBD* 22 | 23 | 24 | :mini:`meth (Arg₁: module):path` 25 | *TBD* 26 | 27 | 28 | :mini:`meth (Buffer: string::buffer):append(Value: module)` 29 | Appends a representation of :mini:`Value` to :mini:`Buffer`. 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/library/object.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | object 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type class < type` 13 | Type of all object classes. 14 | 15 | 16 | :mini:`fun class(Parents: class, ..., Fields: method, ..., Exports: names, ...): class` 17 | Returns a new class inheriting from :mini:`Parents`, with fields :mini:`Fields` and exports :mini:`Exports`. The special exports :mini:`::of` and :mini:`::init` can be set to override the default conversion and initialization behaviour. The :mini:`::new` export will *always* be set to the original constructor for this class. 18 | 19 | 20 | :mini:`meth (Arg₁: class):fields` 21 | *TBD* 22 | 23 | 24 | :mini:`type field` 25 | *TBD* 26 | 27 | 28 | :mini:`type field::mutable < field` 29 | *TBD* 30 | 31 | 32 | :mini:`meth (Arg₁: method):MLMethodDefault(Arg₂: field::modifier)` 33 | *TBD* 34 | 35 | 36 | :mini:`meth (Arg₁: method):MLMethodDefault(Arg₂: watched)` 37 | *TBD* 38 | 39 | 40 | :mini:`type object` 41 | Parent type of all object classes. 42 | 43 | 44 | :mini:`meth (Object: object) :: (Field: string): field` 45 | Retrieves the field :mini:`Field` from :mini:`Object`. Mainly intended for unpacking objects. 46 | 47 | 48 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: object)` 49 | *TBD* 50 | 51 | 52 | :mini:`type property` 53 | A value with an associated setter function. 54 | 55 | 56 | :mini:`fun property(Value: any, Set: function): property` 57 | Returns a new property which dereferences to :mini:`Value`. Assigning to the property will call :mini:`Set(NewValue)`. 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/library/runtime.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | runtime 8 | ======= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun backtrace()` 13 | *TBD* 14 | 15 | 16 | :mini:`fun break(Condition?: any)` 17 | If a debugger is present and :mini:`Condition` is omitted or not :mini:`nil` then triggers a breakpoint. 18 | 19 | 20 | :mini:`fun callcc()` 21 | *TBD* 22 | 23 | 24 | :mini:`fun calldc()` 25 | *TBD* 26 | 27 | 28 | :mini:`fun trace(): list[tuple[string, integer]]` 29 | Returns the call stack trace (source locations). 30 | 31 | 32 | :mini:`fun atomic(Args: any, ..., Fn: function): any` 33 | Calls :mini:`Fn(Args)` in a new context without a scheduler and returns the result. 34 | 35 | 36 | :mini:`fun finalize(Value: any, Fn: function)` 37 | Registers :mini:`Fn` as the finalizer for :mini:`Value`. 38 | 39 | 40 | :mini:`fun markcc(Arg₁: any)` 41 | *TBD* 42 | 43 | 44 | :mini:`meth (Arg₁: channel):error(Arg₂: string, Arg₃: string)` 45 | *TBD* 46 | 47 | 48 | :mini:`meth (Arg₁: channel):raise(Arg₂: error::value)` 49 | *TBD* 50 | 51 | 52 | :mini:`meth (Arg₁: channel):raise(Arg₂: string, Arg₃: any)` 53 | *TBD* 54 | 55 | 56 | :mini:`type debugger` 57 | *TBD* 58 | 59 | 60 | :mini:`meth (Arg₁: error::value):value` 61 | *TBD* 62 | 63 | 64 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: error::value)` 65 | *TBD* 66 | 67 | 68 | :mini:`type resumable::state < state` 69 | *TBD* 70 | 71 | 72 | :mini:`type state < function` 73 | *TBD* 74 | 75 | 76 | :mini:`fun swapcc(Arg₁: state)` 77 | *TBD* 78 | 79 | 80 | :mini:`type uninitialized` 81 | An uninitialized value. Used for forward declarations. 82 | 83 | 84 | :mini:`meth (Arg₁: uninitialized) :: (Arg₂: string)` 85 | *TBD* 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/library/rwlock.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | rwlock 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type rwlock` 13 | A read-write lock for synchronizing concurrent code. 14 | 15 | 16 | :mini:`fun rwlock(): rwlock` 17 | Returns a new read-write lock. 18 | 19 | 20 | :mini:`meth (Lock: rwlock):rdlock` 21 | Locks :mini:`Lock` for reading, waiting if there are any writers using or waiting to use :mini:`Lock`. 22 | 23 | 24 | :mini:`meth (Lock: rwlock):unlock` 25 | Unlocks :mini:`Lock`, resuming any waiting writers or readers (giving preference to writers). 26 | 27 | 28 | :mini:`meth (Lock: rwlock):wrlock` 29 | Locks :mini:`Lock` for reading, waiting if there are any readers or other writers using :mini:`Lock`. 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/library/semaphore.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | semaphore 8 | ========= 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type semaphore` 13 | A semaphore for synchronizing concurrent code. 14 | 15 | 16 | :mini:`fun semaphore(Initial?: integer): semaphore` 17 | Returns a new semaphore with initial value :mini:`Initial` or :mini:`1` if no initial value is specified. 18 | 19 | 20 | :mini:`meth (Semaphore: semaphore):signal: integer` 21 | Increments the internal value in :mini:`Semaphore`, resuming any waiters. Returns the new value. 22 | 23 | 24 | :mini:`meth (Semaphore: semaphore):value: integer` 25 | Returns the internal value in :mini:`Semaphore`. 26 | 27 | 28 | :mini:`meth (Semaphore: semaphore):wait: integer` 29 | Waits until the internal value in :mini:`Semaphore` is postive, then decrements it and returns the new value. 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/library/socket.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | socket 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type socket < stream::fd` 13 | *TBD* 14 | 15 | 16 | :mini:`meth (Arg₁: socket):listen(Arg₂: integer)` 17 | *TBD* 18 | 19 | 20 | :mini:`type socket::inet < socket` 21 | *TBD* 22 | 23 | 24 | :mini:`meth (Arg₁: socket::inet):accept` 25 | *TBD* 26 | 27 | 28 | :mini:`meth (Arg₁: socket::inet):bind(Arg₂: integer)` 29 | *TBD* 30 | 31 | 32 | :mini:`meth (Arg₁: socket::inet):bind(Arg₂: string, Arg₃: integer)` 33 | *TBD* 34 | 35 | 36 | :mini:`meth (Arg₁: socket::inet):connect(Arg₂: string, Arg₃: integer)` 37 | *TBD* 38 | 39 | 40 | :mini:`type socket::local < socket` 41 | *TBD* 42 | 43 | 44 | :mini:`meth (Arg₁: socket::local):accept` 45 | *TBD* 46 | 47 | 48 | :mini:`meth (Arg₁: socket::local):bind(Arg₂: string)` 49 | *TBD* 50 | 51 | 52 | :mini:`meth (Arg₁: socket::local):connect(Arg₂: string)` 53 | *TBD* 54 | 55 | 56 | :mini:`type socket::type < enum` 57 | * :mini:`::Stream` 58 | * :mini:`::DGram` 59 | * :mini:`::Raw` 60 | 61 | 62 | :mini:`fun mlsocketinet(Arg₁: socket::type)` 63 | *TBD* 64 | 65 | 66 | :mini:`fun mlsocketlocal(Arg₁: socket::type)` 67 | *TBD* 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/library/symbol.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | symbol 8 | ====== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`type symbol < function` 13 | *TBD* 14 | 15 | 16 | :mini:`meth (Arg₁: symbol) :: (Arg₂: string)` 17 | *TBD* 18 | 19 | 20 | :mini:`meth (Arg₁: symbol) .. (Arg₂: symbol)` 21 | *TBD* 22 | 23 | 24 | :mini:`type symbol::interval` 25 | *TBD* 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/library/table.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | table 8 | ===== 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`meth table(Arg₁: map, ...)` 13 | *TBD* 14 | 15 | 16 | :mini:`meth table(Arg₁₁ is Value₁, Arg₂: any, ...)` 17 | *TBD* 18 | 19 | 20 | :mini:`meth table(Arg₁₁ is Value₁, Arg₂: type, ...)` 21 | *TBD* 22 | 23 | 24 | :mini:`meth (Arg₁: string::buffer):AppendMethod(Arg₂: table)` 25 | *TBD* 26 | 27 | 28 | :mini:`type table < sequence` 29 | A table is a set of named arrays. The arrays must have the same length. 30 | 31 | 32 | :mini:`meth table()` 33 | *TBD* 34 | 35 | 36 | :mini:`meth (Arg₁: table) :: (Arg₂: string)` 37 | *TBD* 38 | 39 | 40 | :mini:`meth (Arg₁: table)[Arg₂: integer]` 41 | *TBD* 42 | 43 | 44 | :mini:`meth (Arg₁: table)[Arg₂: string]` 45 | *TBD* 46 | 47 | 48 | :mini:`meth (Arg₁: table):capacity` 49 | *TBD* 50 | 51 | 52 | :mini:`meth (Arg₁: table):columns` 53 | *TBD* 54 | 55 | 56 | :mini:`meth (Arg₁: table):delete(Arg₂: string)` 57 | *TBD* 58 | 59 | 60 | :mini:`meth (Arg₁: table):insert(Arg₂: integer, Arg₃₁ is Value₁, ...)` 61 | *TBD* 62 | 63 | 64 | :mini:`meth (Arg₁: table):insert(Arg₂₁ is Value₁, Arg₃: array, ...)` 65 | *TBD* 66 | 67 | 68 | :mini:`meth (Arg₁: table):insert(Arg₂: string, Arg₃: array)` 69 | *TBD* 70 | 71 | 72 | :mini:`meth (Arg₁: table):length` 73 | *TBD* 74 | 75 | 76 | :mini:`meth (Arg₁: table):offset` 77 | *TBD* 78 | 79 | 80 | :mini:`meth (Arg₁: table):push(Arg₂₁ is Value₁, ...)` 81 | *TBD* 82 | 83 | 84 | :mini:`meth (Arg₁: table):put(Arg₂₁ is Value₁, ...)` 85 | *TBD* 86 | 87 | 88 | :mini:`type table::column` 89 | *TBD* 90 | 91 | 92 | :mini:`type table::row` 93 | *TBD* 94 | 95 | 96 | :mini:`meth (Arg₁: table::row) :: (Arg₂: string)` 97 | *TBD* 98 | 99 | 100 | :mini:`meth (Arg₁: table::row)[Arg₂: string]` 101 | *TBD* 102 | 103 | 104 | :mini:`meth (Buffer: string::buffer):append(Value: table::row)` 105 | Appends a representation of :mini:`Value` to :mini:`Buffer`. 106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/library/uuid.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | uuid 8 | ==== 9 | 10 | .. rst-class:: mini-api 11 | 12 | .. note:: 13 | Depending on how *Minilang* is built, :mini:`uuid` might need to be imported using :mini:`import: uuid("util/uuid")`. 14 | 15 | :mini:`meth address(UUID: uuid): address` 16 | Returns an address view of :mini:`UUID`. 17 | 18 | .. code-block:: mini 19 | 20 | import: uuid("util/uuid") 21 | address(uuid()) :> <16:CEAC355E8BA24C51A8ACC890FE423F3E> 22 | 23 | 24 | :mini:`type uuid` 25 | A UUID. 26 | 27 | 28 | :mini:`meth uuid(Address: address): uuid | error` 29 | Returns a new UUID with the bytes of :mini:`Address`. 30 | 31 | 32 | :mini:`meth uuid(String: string): uuid | error` 33 | Parses :mini:`String` as a UUID, returning an error if :mini:`String` does not have the correct format. 34 | 35 | .. code-block:: mini 36 | 37 | import: uuid("util/uuid") 38 | uuid("5fe1af82-02f9-429a-8787-4a7c16628a02") 39 | :> 5fe1af82-02f9-429a-8787-4a7c16628a02 40 | uuid("test") :> error("UUIDError", "Invalid UUID string") 41 | 42 | 43 | :mini:`meth uuid(): uuid` 44 | Returns a new random UUID. 45 | 46 | .. code-block:: mini 47 | 48 | import: uuid("util/uuid") 49 | uuid() :> 0a79bfad-2f25-45a4-b9d4-1fcb8e38f46e 50 | 51 | 52 | :mini:`meth (Arg₁: uuid) <> (Arg₂: uuid)` 53 | *TBD* 54 | 55 | 56 | :mini:`meth (Buffer: string::buffer):append(UUID: uuid)` 57 | Appends a representation of :mini:`UUID` to :mini:`Buffer`. 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/library/xe.rst: -------------------------------------------------------------------------------- 1 | .. include:: 2 | 3 | .. include:: 4 | 5 | .. include:: 6 | 7 | xe 8 | == 9 | 10 | .. rst-class:: mini-api 11 | 12 | :mini:`fun xe::parse(String: string): xe::node` 13 | *TBD* 14 | 15 | 16 | :mini:`type xe::node < sequence` 17 | *TBD* 18 | 19 | 20 | :mini:`fun xe::node(Tag: string): xe::node` 21 | *TBD* 22 | 23 | 24 | :mini:`meth (Arg₁: xe::node)[Arg₂: any]` 25 | *TBD* 26 | 27 | 28 | :mini:`meth (Arg₁: xe::node):attributes` 29 | *TBD* 30 | 31 | 32 | :mini:`meth (Arg₁: xe::node):content` 33 | *TBD* 34 | 35 | 36 | :mini:`meth (Arg₁: xe::node):tag` 37 | *TBD* 38 | 39 | 40 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: xe::node)` 41 | *TBD* 42 | 43 | 44 | :mini:`type xe::var` 45 | *TBD* 46 | 47 | 48 | :mini:`fun xe::var(Name: string): xe::var` 49 | *TBD* 50 | 51 | 52 | :mini:`meth (Arg₁: xe::var):indices` 53 | *TBD* 54 | 55 | 56 | :mini:`meth (Arg₁: xe::var):name` 57 | *TBD* 58 | 59 | 60 | :mini:`meth (Arg₁: string::buffer):append(Arg₂: xe::var)` 61 | *TBD* 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinxcontrib-domaintools 3 | sphinxcontrib-fulltoc 4 | sphinxcontrib-ansi 5 | sphinx_toolbox 6 | sphinx-a4doc 7 | insipid-sphinx-theme 8 | graphviz 9 | breathe 10 | -------------------------------------------------------------------------------- /docs/topics.rst: -------------------------------------------------------------------------------- 1 | Topics 2 | ====== 3 | 4 | .. toctree:: 5 | :glob: 6 | :maxdepth: 2 7 | 8 | /topics/* -------------------------------------------------------------------------------- /docs/topics/classes.rst: -------------------------------------------------------------------------------- 1 | Classes 2 | ======= 3 | 4 | User defined classes can be created using the :mini:`class()` constructor, see :ref:`here `. Usually classes are defined using a compound declaration. 5 | 6 | :mini:`class(Arg₁, Arg₂, ...)` 7 | Creates a new class with additional properties based on the types of :mini:`Arg₁, Arg₂, ...`: 8 | 9 | :mini:`class` 10 | Adds a parent class. Multiple parent classes are allowed. 11 | 12 | :mini:`method` 13 | Adds a field. Instances of this class will have space allocated for all fields, fields cannot be added or removed from instances later. Fields are accessed using the associated method. 14 | 15 | :mini:`Name is Value` 16 | Named arguments add shared values to the class. If :mini:`Class` is a class, then :mini:`Class::Name` will return the shared value called *Name*. 17 | 18 | Certain shared values have special meaning. If :mini:`c` is a class, then: 19 | 20 | * The name :mini:`c::new` is always set to a function equivalent to the following: 21 | 22 | .. code-block:: mini 23 | :linenos: 24 | 25 | fun(Arg₁, Arg₂, ...) do 26 | let Instance := new instance of c 27 | c::init(Instance, Arg₁, Arg₂, ...) 28 | ret Instance 29 | end 30 | 31 | This cannot be overridden, if *new* is passed as a named argument to :mini:`class()`, it is ignored. 32 | 33 | * The value of :mini:`c::init` is used as the initializer and should be a callable value (function, method, etc). This value is called by :mini:`c::new` to initialize a new instance :mini:`c` with the given arguments. 34 | 35 | If *init* is not set, a default initializer is set which assigns positional arguments to the instance fields in order. Any named arguments are assigned to the corresponding field by name. 36 | 37 | * The value of :mini:`c::of` is used as the constructor and should be a callable value (function, method, etc). This value is called when the class is called as a function, i.e. :mini:`c(...)` is equivalent to :mini:`c::of(...)`. 38 | 39 | If *of* is not set, a default constructor is set which simply calls :mini:`c::new`. 40 | 41 | Methods 42 | ------- 43 | 44 | Like all types in *Minilang*, classes can be used to define :doc:`/topics/methods`. 45 | 46 | Examples 47 | -------- 48 | 49 | .. code-block:: mini 50 | :linenos: 51 | 52 | class: account(:Balance, 53 | init is fun(Account, Balance) do 54 | Account:Balance := Balance 55 | end 56 | ) 57 | 58 | meth :deposit(Account: account, Amount: real) do 59 | Account:Balance := old + Amount 60 | end 61 | 62 | meth :withdraw(Account: account, Amount: real) do 63 | Account:Balance := old - Amount 64 | end 65 | 66 | let Account := account(100) 67 | Account:deposit(200) 68 | Account:withdraw(150) 69 | print('Balance = {Account:Balance}\n') 70 | 71 | .. code-block:: console 72 | 73 | Balance = 150 74 | 75 | -------------------------------------------------------------------------------- /docs/topics/conditionals.rst: -------------------------------------------------------------------------------- 1 | Conditionals 2 | ============ 3 | 4 | *Minilang* has several constructs for conditional evaluation of code. 5 | 6 | .. important:: 7 | 8 | All conditional evaluation constructs treat **only** :mini:`nil` as the false-like or negative value, and **all other values** as true-like or positive. Boolean values (:mini:`true` and :mini:`false`) are not :mini:`nil` and hence treated as true-like or positive. 9 | 10 | And / or expressions 11 | -------------------- 12 | 13 | These expressions check their left argument for :mini:`nil` and only evaluate their right argument if necessary. 14 | 15 | .. parser-rule-diagram:: expression ( 'and' | 'or' ) expression 16 | 17 | They operate as follows: 18 | 19 | .. list-table:: 20 | :header-rows: 1 21 | 22 | * - Expression 23 | - Result of :mini:`X` 24 | - :mini:`Y` evaluated 25 | - Result 26 | 27 | * - :mini:`X and Y` 28 | - :mini:`nil` 29 | - No 30 | - :mini:`X` (:mini:`nil`) 31 | 32 | * - :mini:`X and Y` 33 | - Not :mini:`nil` 34 | - Yes 35 | - :mini:`Y` 36 | 37 | * - :mini:`X or Y` 38 | - :mini:`nil` 39 | - Yes 40 | - :mini:`Y` 41 | 42 | * - :mini:`X or Y` 43 | - Not :mini:`nil` 44 | - No 45 | - :mini:`X` 46 | 47 | If expressions 48 | -------------- 49 | 50 | An :mini:`if`-expression evaluates its condition expressions and evaluates the :mini:`then`-block if the condition value is not :mini:`nil`. Otherwise it evaluates the :mini:`else`-block is present, or :mini:`nil` otherwise. Additional :mini:`elseif` branches can used to avoid nesting the :mini:`else` blocks. 51 | 52 | The condition value itself can optionally contain a variable declaration using :mini:`let` or :mini:`var` (including an unpacking declaration) allowing a computed value such as a regular expression match to be used as the condition without needing an extra declaration. 53 | 54 | .. parser-rule-diagram:: 'if' ( ( 'var' | 'let' ) ( identifier | ( '(' ( identifier | '_' ) ( ',' ( identifier | '_' ) )* ')' ) ) ':=' )? expression 'then' block ( 'elseif' ( ( 'var' | 'let' ) ( identifier | ( '(' ( identifier | '_' ) ( ',' ( identifier | '_' ) )* ')' ) ) ':=' )? expression 'then' block )* ( 'else' block )? 'end' 55 | 56 | -------------------------------------------------------------------------------- /docs/topics/contexts.rst: -------------------------------------------------------------------------------- 1 | Contexts 2 | ======== 3 | 4 | All code in *Minilang* executes in a *context*. The context defines inherited state such as the current debugger, scheduler, thread (if thread support is enabled) and method table. Additional context specific variables can also be defined. Unless otherwise modified, the context is inherited through each function call. 5 | 6 | Context variables 7 | ----------------- 8 | 9 | New context variables can be created using the :mini:`context()` function. Context variables are callable as functions, and either return the current value of the corresponding variable in the current context, or execute a function in a new context where the corresponding variable is bound to a specific value. 10 | 11 | .. code-block:: mini 12 | :linenos: 13 | 14 | let Var := context() 15 | 16 | Var(100;) do 17 | print('Current value of Var = {Var()}\n') 18 | end 19 | 20 | print('Current value of Var = {Var()}\n') 21 | 22 | 23 | .. code-block:: console 24 | 25 | Current value of Var = 100 26 | Current value of Var = nil 27 | 28 | Host context specific values 29 | ---------------------------- 30 | 31 | Context variables are intended to be defined and used at runtime within *Minilang* code. For faster and more controlled cases, additional context specific values can be defined by the host application when *Minilang* is embedded. Each context specific value is assigned an integer index making lookup faster than *Minilang* defined context variables. 32 | 33 | .. c:function:: int ml_context_index() 34 | 35 | Registers a new context specific value and returns its index. 36 | 37 | .. c:function:: ml_context_t *ml_context(ml_context_t *Parent) 38 | 39 | Creates a new context, inheriting context specific values from `Parent`. 40 | 41 | .. c:function:: void ml_context_set(ml_context_t *Context, int Index, void *Value) 42 | 43 | Sets the context specific value with the specified index. `Context` should be a newly created context, it's usually incorrect to modify an existing context. 44 | 45 | .. c:function:: void *ml_context_get(ml_context_t *Context, int Index) 46 | 47 | Gets the context specific value with the specified index. 48 | 49 | Predefined indicies 50 | ................... 51 | 52 | The following context specific value indices are predefined in *Minilang*. Note that additional context specific values may be defined in the future, the functions above are the only safe way to define and use new context specific values in a host application. 53 | 54 | * :c:`ML_METHOD_INDEX`: used to hold the context specific method table. Can be used to restrict method definitions to specific contexts (e.g. in multi-tenant code). 55 | * :c:`ML_DEBUGGER_INDEX`: used to hold the current debugger, if any. 56 | * :c:`ML_SCHEDULER_INDEX`: used to hold information about the current scheduler. 57 | 58 | -------------------------------------------------------------------------------- /docs/topics/errors.rst: -------------------------------------------------------------------------------- 1 | Error Handling 2 | ============== 3 | 4 | When an error occurs in *Minilang*, an error value is created and returned. If an error handler has been declared in the current block, execution jumps to the error handler, assigning the error value to the error variable. If no error handler declared, the error is propagated to the surrounding block, or returned from the current function if the outermost block is reached without any error handler. 5 | 6 | .. parser-rule-diagram:: 'on' block 7 | 8 | .. code-block:: mini 9 | :linenos: 10 | 11 | for I in -5 .. 5 do 12 | print('1 / {I} = {1 / I}\n') 13 | on Error do 14 | print('{Error:type}: {Error:message}\n') 15 | end 16 | 17 | .. code-block:: console 18 | 19 | 1 / -5 = -0.2 20 | 1 / -4 = -0.25 21 | 1 / -3 = -0.333333 22 | 1 / -2 = -0.5 23 | 1 / -1 = -1 24 | ValueError: Division by 0 25 | 1 / 1 = 1 26 | 1 / 2 = 0.5 27 | 1 / 3 = 0.333333 28 | 1 / 4 = 0.25 29 | 1 / 5 = 0.2 30 | 31 | .. note:: 32 | 33 | Within an error handler, an error value is wrapped inside another value (with type :mini:`error`) in order to prevent it triggering another error each time it isused. The wrapped error value provides access to the error type, message and call history, and allows the original error to be raised again using :mini:`:raise`. 34 | 35 | Generating Errors 36 | ----------------- 37 | 38 | The function :mini:`error(Type, Message)` returns a new error, triggering the error handler in the calling function. 39 | 40 | .. code-block:: mini 41 | :linenos: 42 | 43 | fun fact(N: integer) do 44 | N >= 0 or error("RangeError", "Factorial requires non-negative integer") 45 | var F := 1 46 | for I in 1 .. N do 47 | F := old * I 48 | end 49 | ret F 50 | end 51 | 52 | for N in [1, 5, -7, 0.4] do 53 | print('{N}! = {fact(N)}\n') 54 | on Error do 55 | print('{N}! caused {Error:type}: {Error:message}\n') 56 | end 57 | 58 | .. code-block:: console 59 | 60 | 1! = 1 61 | 5! = 120 62 | -7! caused RangeError: Factorial requires non-negative integer 63 | 0.4! caused TypeError: Expected integer not double for argument 1 64 | 65 | The previous example also shows how the optional type checking can be enabled for function arguments. 66 | 67 | Error Payloads 68 | -------------- 69 | 70 | As well as an error message, an error value can also hold any other *Minilang* value. To construct such an error value, the function :mini:`raise(Type, Value)` can be used. The value held by an error can be retrieved using :mini:`:value`. For errors not created by :mini:`raise` (including all normal runtime errors), :mini:`Error:value` will return :mini:`nil`. 71 | -------------------------------------------------------------------------------- /docs/topics/guards.rst: -------------------------------------------------------------------------------- 1 | Guards 2 | ====== 3 | 4 | Simple Guards 5 | ------------- 6 | 7 | :mini:`nil` is used throughout *Minilang* to denote the absence of any other value. This includes the initial values of variables or object fields before assignment, indexing a :mini:`map` or :mini:`list` with a missing key or index and the result of binary comparisons which are logically false. 8 | 9 | .. code-block:: mini 10 | :linenos: 11 | 12 | var X 13 | X :> nil 14 | let L := [1, 2, 3] 15 | L[4] :> nil 16 | let M := {"A" is 1, "B" is 2} 17 | M["C"] :> nil 18 | 2 < 1 :> nil 19 | 20 | As a result, it is often required to check the result of an expression for :mini:`nil` before using the result in a function call. 21 | 22 | .. code-block:: mini 23 | :linenos: 24 | 25 | let M := {"A" is [1, 2], "B" is [3, 4]} 26 | M["A"][1] :> 1 27 | M["C"][1] :> MethodError: no method found for [](nil, int32) 28 | 29 | if let T := M["A"] then T[1] end :> 1 30 | if let T := M["C"] then T[1] end :> nil 31 | 32 | *Minilang* provides a shorthand for this type of check using *guarded* arguments. A simple guarded argument consists of an empty pair of braces :mini:`{}` following an expression in a function call. 33 | 34 | .. parser-rule-diagram:: expression '{' '}' 35 | 36 | If the expression in a simple guarded argument evaluates to :mini:`nil` then the **innermost** function call containing the guarded argument evaluates immediately to :mini:`nil` without invoking the called function. 37 | 38 | .. code-block:: mini 39 | :linenos: 40 | 41 | let M := {"A" is [1, 2], "B" is [3, 4]} 42 | M["A"]{}[1] :> 1 43 | M["C"]{}[1] :> nil 44 | 45 | General Guards 46 | -------------- 47 | 48 | Other than simply checking for :mini:`nil`, guarded arguments can also check their preceeding expression for arbitrarily complex conditions by including another expression inside the braces. Within the braces, the keyword :mini:`it` refers to the value of the preceeding expression. 49 | 50 | .. parser-rule-diagram:: expression '{' expression '}' 51 | 52 | .. code-block:: mini 53 | :linenos: 54 | 55 | for I in 1 .. 10 do 56 | print("I = ", I{2 | it}, "\n") 57 | end 58 | 59 | .. code-block:: console 60 | 61 | I = 2 62 | I = 4 63 | I = 6 64 | I = 8 65 | I = 10 66 | -------------------------------------------------------------------------------- /docs/topics/macros.rst: -------------------------------------------------------------------------------- 1 | Macros 2 | ====== 3 | 4 | *Minilang* provides some support for meta-programming using macros. During compilation, function calls which meet certain criteria are treated as macro expansions: 5 | 6 | #. The function being called must evaluate to a constant value at the *compilation* stage, and 7 | #. The constant value is a :mini:`macro` value. 8 | 9 | In this situation, the compiler applies the macro with the specified arguments passed as *expression* values. The macro must then return another *expression* value which the compiler then compiles in place of the original function call. 10 | 11 | This method of implementing macros is different to most other languages that support macros in that the substitution is performed *during* compilation rather than *before*. 12 | 13 | :mini:`macro` is a normal *Minilang* type and macros can be defined using a constant declaration (either :mini:`def name := macro(Callback)` or the compact alternative :mini:`macro: name(Callback)`). For example: 14 | 15 | .. code-block:: mini 16 | :linenos: 17 | 18 | macro: log(; Expr) do 19 | :{print('[{:$Source}:{:$Line}] {:$Expr}\n'), Expr is Expr, Source is macro::value(Expr:source), Line is macro::value(Expr:start)} 20 | end 21 | 22 | log(1 + 1) 23 | 24 | .. code-block:: console 25 | 26 | [:1] 2 27 | -------------------------------------------------------------------------------- /docs/topics/methods.rst: -------------------------------------------------------------------------------- 1 | Methods 2 | ======= 3 | 4 | All methods in *Minilang* are multimethods, that is they use the runtime types of all arguments to determine which function to call. 5 | 6 | Methods are written as :mini:`:name` (or :mini:`:"name"` if *name* contains non-alphanumeric characters). Methods also act as *atoms* or *symbols*, two methods with the same name are identically equal. Infix operators such as :mini:`+`, :mini:`*`, etc, are equivalent to methods with the same name (:mini:`:"+"`, :mini:`:"*"`, etc). 7 | 8 | If no suitable method is found for a specific combination of arguments, an error is raised. Methods can be defined using the :mini:`meth` keyword: 9 | 10 | .. parser-rule-diagram:: 'meth' term '(' ( 11 | ( identifier ':' expression ( ',' identifier ':' expression )* ( ',' '[' identifier ']' )? ( ',' '{' identifier '}' )? ) | 12 | ( '[' identifier ']' ( ',' '{' identifier '}' )? ) | 13 | ( '{' identifier '}' ) 14 | )? ')' ':='? expression 15 | 16 | .. code-block:: mini 17 | :linenos: 18 | 19 | print('5 * \"word\" = {5 * "word"}\n') 20 | 21 | .. code-block:: console 22 | 23 | MethodError: no method found for *(int32, string) 24 | :1 25 | 26 | .. code-block:: mini 27 | :linenos: 28 | 29 | meth *(Count: integer, String: string) sum(1 .. Count;) String 30 | 31 | print('5 * \"word\" = {5 * "word"}\n') 32 | 33 | .. code-block:: console 34 | 35 | 5 * "word" = wordwordwordwordword 36 | 37 | -------------------------------------------------------------------------------- /docs/topics/modules.rst: -------------------------------------------------------------------------------- 1 | Modules 2 | ======= 3 | 4 | -------------------------------------------------------------------------------- /docs/topics/must.rst: -------------------------------------------------------------------------------- 1 | Must 2 | ==== 3 | 4 | A :mini:`must`-declaration can be used to ensure that particular code is guaranteed to run before a block is finished, even if an error occurs or :mini:`ret`, :mini:`exit`, :mini:`while`, :mini:`until` or :mini:`next` is used to exit the block early. 5 | 6 | .. parser-rule-diagram:: 'must' expression 7 | 8 | .. note:: 9 | 10 | Since :mini:`susp`-expressions can resume the current block, they do not run :mini:`must` code. In general, do not use :mini:`must`-declarations with :mini:`susp`-expressions unless it known that the generating function will always be completed. 11 | 12 | .. note:: 13 | 14 | In order to guarantee a valid state when each :mini:`must`-expression is executed, each :mini:`must`-declaration implicitly creates a new block around the code that follows it. Given code like: 15 | 16 | .. code-block:: mini 17 | :linenos: 18 | 19 | decls 20 | code 21 | must X 22 | decls 23 | code 24 | 25 | the compiler treats it internally as similar to: 26 | 27 | .. code-block:: mini 28 | :linenos: 29 | 30 | decls 31 | code 32 | do 33 | decls 34 | code 35 | X 36 | on Error do 37 | X 38 | Error:raise 39 | end 40 | 41 | This means that some forward declarations that work without :mini:`must` may not work when :mini:`must` is present. This limitation might be removed in the future. 42 | -------------------------------------------------------------------------------- /docs/topics/scheduler.rst: -------------------------------------------------------------------------------- 1 | Scheduler 2 | ========= 3 | 4 | -------------------------------------------------------------------------------- /docs/topics/types.rst: -------------------------------------------------------------------------------- 1 | Types 2 | ===== 3 | 4 | Each value in *Minilang* has a type which can be determined at runtime. The types of values are used for deciding how operations and methods behave on those values. The type of a value can be obtained using :mini:`type(Value)`. Types are usually displayed as :samp:`<<{NAME}>>`. 5 | 6 | .. code-block:: mini 7 | :linenos: 8 | 9 | print(type(1)) 10 | print(type(1.0)) 11 | print(type("Hello world")) 12 | print(type([])) 13 | 14 | .. code-block:: console 15 | 16 | <> 17 | <> 18 | <> 19 | <> 20 | 21 | Types are values themselves, and can be stored in variables or passed to functions. The type of a type is :mini:`type`. 22 | 23 | .. code-block:: mini 24 | :linenos: 25 | 26 | print(type) 27 | print(type(string)) 28 | print(type(type)) 29 | 30 | .. code-block:: console 31 | 32 | <> 33 | <> 34 | <> 35 | 36 | Types are Functions 37 | ------------------- 38 | 39 | This reveals an important feature of *Minilang*; types can be used as functions. Calling a type as a function is the *Minilang* way of constructing values of a given type. 40 | 41 | .. code-block:: mini 42 | :linenos: 43 | 44 | let S := string(1234) 45 | print('{S} -> {type(S)}\n') 46 | 47 | .. code-block:: console 48 | 49 | 1234 -> <> 50 | 51 | Type Inheritance 52 | ---------------- 53 | 54 | Each type in *Minilang* can optionally have parent types. Values of a type inherit behaviour from its parent types, unless that behaviour is overridden in the child type. The set of all types in *Minilang* forms a tree under inheritance. A subset of that tree is shown in the :doc:`/library/hierarchy`. 55 | 56 | The parents of a type can be obtained using :mini:`Type:parents`. The result is returned as a list in no particular order. 57 | 58 | .. code-block:: mini 59 | :linenos: 60 | 61 | print(type(1)) 62 | print(type(1):parents) 63 | 64 | .. code-block:: console 65 | 66 | <> 67 | [<>, <>, <>, <>, <>] 68 | 69 | Types have Exports 70 | ------------------ 71 | 72 | Types in *Minilang* can also have named exports, accessible as :mini:`Type::Name`. This is used to collect related values by type, and allows types to be used as modules (when *Minilang* is built with module support). 73 | 74 | .. code-block:: mini 75 | :linenos: 76 | 77 | print(real::random(10)) 78 | print(real::Inf) 79 | 80 | .. code-block:: console 81 | 82 | 5.084 83 | inf 84 | 85 | Generic Types 86 | ------------- 87 | 88 | *Minilang* can be built with support for generic types. These are types that are parameterised by other types, along with rules for determining whether one generic type is a parent type of another. 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/tutorial.rst: -------------------------------------------------------------------------------- 1 | Tutorial 2 | ======== 3 | 4 | .. toctree:: 5 | :glob: 6 | :maxdepth: 1 7 | 8 | /tutorial/* 9 | -------------------------------------------------------------------------------- /docs/tutorial/01_basics.rst: -------------------------------------------------------------------------------- 1 | Minilang Basics 2 | =============== 3 | 4 | Values 5 | ------ 6 | 7 | Here's some sample *Minilang* code. 8 | 9 | .. tryit:: 10 | 11 | 2 12 | 3.14 13 | "Hello world!" 14 | 15 | [1, 2, 3] 16 | {"a" is 1, "b" is 2, "c" is 3} 17 | 18 | -------------------------------------------------------------------------------- /sed.txt: -------------------------------------------------------------------------------- 1 | s/);/);\ 2 | /g -------------------------------------------------------------------------------- /src/array/compare_eq.c: -------------------------------------------------------------------------------- 1 | #include "compare_impl_complex.h" 2 | 3 | #define EQ(A, B) A == B 4 | 5 | extern ml_value_t *EqualMethod; 6 | 7 | COMPARE_FNS(Eq, eq, EQ, EqualMethod); 8 | -------------------------------------------------------------------------------- /src/array/compare_ge.c: -------------------------------------------------------------------------------- 1 | #include "compare_impl_real.h" 2 | 3 | #define GE(A, B) A >= B 4 | 5 | extern ml_value_t *GreaterEqualMethod; 6 | 7 | COMPARE_FNS(Ge, ge, GE, GreaterEqualMethod); 8 | -------------------------------------------------------------------------------- /src/array/compare_gt.c: -------------------------------------------------------------------------------- 1 | #include "compare_impl_real.h" 2 | 3 | #define GT(A, B) A > B 4 | 5 | extern ml_value_t *GreaterMethod; 6 | 7 | COMPARE_FNS(Gt, gt, GT, GreaterMethod); 8 | -------------------------------------------------------------------------------- /src/array/compare_le.c: -------------------------------------------------------------------------------- 1 | #include "compare_impl_real.h" 2 | 3 | #define LE(A, B) A <= B 4 | 5 | extern ml_value_t *LessEqualMethod; 6 | 7 | COMPARE_FNS(Le, le, LE, LessEqualMethod); 8 | -------------------------------------------------------------------------------- /src/array/compare_lt.c: -------------------------------------------------------------------------------- 1 | #include "compare_impl_real.h" 2 | 3 | #define LT(A, B) A < B 4 | 5 | extern ml_value_t *LessMethod; 6 | 7 | COMPARE_FNS(Lt, lt, LT, LessMethod); 8 | -------------------------------------------------------------------------------- /src/array/compare_ne.c: -------------------------------------------------------------------------------- 1 | #include "compare_impl_complex.h" 2 | 3 | #define NE(A, B) A != B 4 | 5 | extern ml_value_t *NotEqualMethod; 6 | 7 | COMPARE_FNS(Ne, ne, NE, NotEqualMethod); 8 | -------------------------------------------------------------------------------- /src/array/update_add.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_complex.h" 2 | 3 | #define OP_ADD(A, B) A + B 4 | 5 | extern ml_value_t *AddMethod; 6 | 7 | static ml_value_t *value_add(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(AddMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Add, add, OP_ADD, value_add); 13 | -------------------------------------------------------------------------------- /src/array/update_and.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_integer.h" 2 | 3 | #define OP_AND(A, B) A & B 4 | 5 | extern ml_value_t *AndMethod; 6 | 7 | static ml_value_t *value_and(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(AndMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(And, and, OP_AND, value_and); 13 | -------------------------------------------------------------------------------- /src/array/update_div.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_complex.h" 2 | 3 | #define OP_DIV(A, B) A / B 4 | 5 | extern ml_value_t *DivMethod; 6 | 7 | static ml_value_t *value_div(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(DivMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Div, div, OP_DIV, value_div); 13 | 14 | #define OP_RDIV(A, B) B / A 15 | 16 | static ml_value_t *value_rdiv(ml_value_t *A, ml_value_t *B) { 17 | ml_value_t *Args[2] = {B, A}; 18 | return ml_simple_call(DivMethod, 2, Args); 19 | } 20 | 21 | UPDATE_FNS(RDiv, rdiv, OP_RDIV, value_rdiv); 22 | -------------------------------------------------------------------------------- /src/array/update_max.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_real.h" 2 | 3 | #define OP_MAX(A, B) (A > B ? A : B) 4 | 5 | extern ml_value_t *MaxMethod; 6 | 7 | static ml_value_t *value_max(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(MaxMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Max, max, OP_MAX, value_max); 13 | -------------------------------------------------------------------------------- /src/array/update_min.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_real.h" 2 | 3 | #define OP_MIN(A, B) (A < B ? A : B) 4 | 5 | extern ml_value_t *MinMethod; 6 | 7 | static ml_value_t *value_min(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(MinMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Min, min, OP_MIN, value_min); 13 | -------------------------------------------------------------------------------- /src/array/update_mul.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_complex.h" 2 | 3 | #define OP_MUL(A, B) A * B 4 | 5 | extern ml_value_t *MulMethod; 6 | 7 | static ml_value_t *value_mul(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(MulMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Mul, mul, OP_MUL, value_mul); 13 | -------------------------------------------------------------------------------- /src/array/update_or.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_integer.h" 2 | 3 | #define OP_OR(A, B) A | B 4 | 5 | extern ml_value_t *OrMethod; 6 | 7 | static ml_value_t *value_or(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(OrMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Or, or, OP_OR, value_or); 13 | -------------------------------------------------------------------------------- /src/array/update_set.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_complex.h" 2 | 3 | #define OP_SET(A, B) B 4 | 5 | UPDATE_FNS(Set, set, OP_SET, OP_SET); 6 | -------------------------------------------------------------------------------- /src/array/update_sub.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_complex.h" 2 | 3 | #define OP_SUB(A, B) A - B 4 | 5 | extern ml_value_t *SubMethod; 6 | 7 | static ml_value_t *value_sub(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(SubMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Sub, sub, OP_SUB, value_sub); 13 | 14 | #define OP_RSUB(A, B) B - A 15 | 16 | static ml_value_t *value_rsub(ml_value_t *A, ml_value_t *B) { 17 | ml_value_t *Args[2] = {B, A}; 18 | return ml_simple_call(SubMethod, 2, Args); 19 | } 20 | 21 | UPDATE_FNS(RSub, rsub, OP_RSUB, value_rsub); 22 | -------------------------------------------------------------------------------- /src/array/update_xor.c: -------------------------------------------------------------------------------- 1 | #include "update_impl_integer.h" 2 | 3 | #define OP_XOR(A, B) A | B 4 | 5 | extern ml_value_t *XorMethod; 6 | 7 | static ml_value_t *value_xor(ml_value_t *A, ml_value_t *B) { 8 | ml_value_t *Args[2] = {A, B}; 9 | return ml_simple_call(XorMethod, 2, Args); 10 | } 11 | 12 | UPDATE_FNS(Xor, xor, OP_XOR, value_xor); 13 | -------------------------------------------------------------------------------- /src/dynasm/dasm_proto.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** DynASM encoding engine prototypes. 3 | ** Copyright (C) 2005-2017 Mike Pall. All rights reserved. 4 | ** Released under the MIT license. See dynasm.lua for full copyright notice. 5 | */ 6 | 7 | #ifndef _DASM_PROTO_H 8 | #define _DASM_PROTO_H 9 | 10 | #include 11 | #include 12 | 13 | #define DASM_IDENT "DynASM 1.3.0" 14 | #define DASM_VERSION 10300 /* 1.3.0 */ 15 | 16 | #ifndef Dst_DECL 17 | #define Dst_DECL dasm_State **Dst 18 | #endif 19 | 20 | #ifndef Dst_REF 21 | #define Dst_REF (*Dst) 22 | #endif 23 | 24 | #ifndef DASM_FDEF 25 | #define DASM_FDEF extern 26 | #endif 27 | 28 | #ifndef DASM_M_GROW 29 | #define DASM_M_GROW(ctx, t, p, sz, need) \ 30 | do { \ 31 | size_t _sz = (sz), _need = (need); \ 32 | if (_sz < _need) { \ 33 | if (_sz < 16) _sz = 16; \ 34 | while (_sz < _need) _sz += _sz; \ 35 | (p) = (t *)realloc((p), _sz); \ 36 | if ((p) == NULL) exit(1); \ 37 | (sz) = _sz; \ 38 | } \ 39 | } while(0) 40 | #endif 41 | 42 | #ifndef DASM_M_FREE 43 | #define DASM_M_FREE(ctx, p, sz) free(p) 44 | #endif 45 | 46 | /* Internal DynASM encoder state. */ 47 | typedef struct dasm_State dasm_State; 48 | 49 | 50 | /* Initialize and free DynASM state. */ 51 | DASM_FDEF void dasm_init(Dst_DECL, int maxsection); 52 | DASM_FDEF void dasm_free(Dst_DECL); 53 | 54 | /* Setup global array. Must be called before dasm_setup(). */ 55 | DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl); 56 | 57 | /* Grow PC label array. Can be called after dasm_setup(), too. */ 58 | DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc); 59 | 60 | /* Setup encoder. */ 61 | DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist); 62 | 63 | /* Feed encoder with actions. Calls are generated by pre-processor. */ 64 | DASM_FDEF void dasm_put(Dst_DECL, int start, ...); 65 | 66 | /* Link sections and return the resulting size. */ 67 | DASM_FDEF int dasm_link(Dst_DECL, size_t *szp); 68 | 69 | /* Encode sections into buffer. */ 70 | DASM_FDEF int dasm_encode(Dst_DECL, void *buffer); 71 | 72 | /* Get PC label offset. */ 73 | DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc); 74 | 75 | #ifdef DASM_CHECKS 76 | /* Optional sanity checker to call between isolated encoding steps. */ 77 | DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch); 78 | #else 79 | #define dasm_checkstep(a, b) 0 80 | #endif 81 | 82 | 83 | #endif /* _DASM_PROTO_H */ 84 | -------------------------------------------------------------------------------- /src/dynasm/dasm_x64.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------ 2 | -- DynASM x64 module. 3 | -- 4 | -- Copyright (C) 2005-2017 Mike Pall. All rights reserved. 5 | -- See dynasm.lua for full copyright notice. 6 | ------------------------------------------------------------------------------ 7 | -- This module just sets 64 bit mode for the combined x86/x64 module. 8 | -- All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | x64 = true -- Using a global is an ugly, but effective solution. 12 | return require("dasm_x86") 13 | -------------------------------------------------------------------------------- /src/exports.lst: -------------------------------------------------------------------------------- 1 | { 2 | extern "C" { 3 | ml_*; 4 | ML*; 5 | stringmap_*; 6 | inthash_*; 7 | GC_*; 8 | __start_ml_context_section; 9 | __stop_ml_context_section; 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /src/inthash.h: -------------------------------------------------------------------------------- 1 | #ifndef INTHASH_H 2 | #define INTHASH_H 3 | 4 | /// \defgroup inthash 5 | /// @{ 6 | /// 7 | 8 | #include 9 | #include 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | typedef struct inthash_t inthash_t; 16 | 17 | struct inthash_t { 18 | uintptr_t *Keys; 19 | void **Values; 20 | int Size, Space; 21 | }; 22 | 23 | #define INTHASH_INDEX_SHIFT 6 24 | #define INTHASH_INCR_SHIFT 9 25 | 26 | #define INTHASH_INIT (inthash_t){NULL, NULL, 0, 0} 27 | 28 | inthash_t *inthash_new() __attribute__ ((malloc)); 29 | 30 | void *inthash_search(const inthash_t *Map, uintptr_t Key) __attribute__ ((pure)); 31 | void *inthash_insert(inthash_t *Map, uintptr_t Key, void *Value); 32 | 33 | static inline void *inthash_search_inline(const inthash_t *Map, uintptr_t Key) { 34 | if (!Map->Size) return NULL; 35 | uintptr_t *Keys = Map->Keys; 36 | size_t Mask = Map->Size - 1; 37 | size_t Index = (Key >> INTHASH_INDEX_SHIFT) & Mask; 38 | if (Keys[Index] == Key) return Map->Values[Index]; 39 | if (Keys[Index] < Key) return NULL; 40 | size_t Incr = (Key >> INTHASH_INCR_SHIFT) | 1; 41 | do { 42 | Index = (Index + Incr) & Mask; 43 | if (Keys[Index] == Key) return Map->Values[Index]; 44 | } while (Keys[Index] > Key); 45 | return NULL; 46 | } 47 | 48 | static inline int inthash_contains_inline(const inthash_t *Map, uintptr_t Key) { 49 | if (!Map->Size) return 0; 50 | uintptr_t *Keys = Map->Keys; 51 | size_t Mask = Map->Size - 1; 52 | size_t Index = (Key >> INTHASH_INDEX_SHIFT) & Mask; 53 | if (Keys[Index] == Key) return 1; 54 | if (Keys[Index] < Key) return 0; 55 | size_t Incr = (Key >> INTHASH_INCR_SHIFT) | 1; 56 | do { 57 | Index = (Index + Incr) & Mask; 58 | if (Keys[Index] == Key) return 1; 59 | } while (Keys[Index] > Key); 60 | return 0; 61 | } 62 | 63 | typedef struct {void *Value; int Present;} inthash_result_t; 64 | 65 | inthash_result_t inthash_search2(const inthash_t *Map, uintptr_t Key) __attribute__ ((pure)); 66 | 67 | static inline inthash_result_t inthash_search2_inline(const inthash_t *Map, uintptr_t Key) { 68 | if (!Map->Size) return (inthash_result_t){NULL, 0}; 69 | uintptr_t *Keys = Map->Keys; 70 | size_t Mask = Map->Size - 1; 71 | size_t Index = (Key >> INTHASH_INDEX_SHIFT) & Mask; 72 | if (Keys[Index] == Key) return (inthash_result_t){Map->Values[Index], 1}; 73 | if (Keys[Index] < Key) return (inthash_result_t){NULL, 0}; 74 | size_t Incr = (Key >> INTHASH_INCR_SHIFT) | 1; 75 | do { 76 | Index = (Index + Incr) & Mask; 77 | if (Keys[Index] == Key) return (inthash_result_t){Map->Values[Index], 1}; 78 | } while (Keys[Index] > Key); 79 | return (inthash_result_t){NULL, 0}; 80 | } 81 | 82 | #ifdef __cplusplus 83 | } 84 | #endif 85 | 86 | /// @} 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/inthash_x64.s: -------------------------------------------------------------------------------- 1 | .intel_syntax 2 | .global inthash_search 3 | .global inthash_search2 4 | 5 | //RDI, RSI, RDX, RCX, R8, R9 (R10) 6 | 7 | .set INDEX_SHIFT, 6 8 | .set INCR_SHIFT, 9 9 | 10 | .text 11 | inthash_search: 12 | // %rdi -> inthash_t Map 13 | // (%rdi) -> uint64_t *Keys 14 | // 8(%rdi) -> void *Values 15 | // 16(%rdi) -> int Size 16 | // 20(%rdi) -> int Space 17 | // %rsi -> uint64_t Key 18 | mov %ecx, [%rdi + 16] 19 | mov %r8, [%rdi + 8] 20 | sub %rcx, 1 21 | jc .L1 22 | mov %rdi, [%rdi] 23 | mov %rax, %rsi 24 | shr %rax, INDEX_SHIFT 25 | and %rax, %rcx 26 | cmp %rsi, [%rdi + %rax * 8] 27 | je .L2 28 | ja .L1 29 | .L3: 30 | mov %rdx, %rsi 31 | shr %rdx, INCR_SHIFT 32 | or %rdx, 1 33 | .L4: 34 | add %rax, %rdx 35 | and %rax, %rcx 36 | cmp %rsi, [%rdi + %rax * 8] 37 | jb .L4 38 | ja .L1 39 | .L2: 40 | mov %rax, [%r8 + %rax * 8] 41 | ret 42 | .L1: 43 | xor %eax, %eax 44 | ret 45 | 46 | .text 47 | inthash_search2: 48 | // %rdi -> inthash_t Map 49 | // (%rdi) -> uint64_t *Keys 50 | // 8(%rdi) -> void *Values 51 | // 16(%rdi) -> int Size 52 | // 20(%rdi) -> int Space 53 | // %rsi -> uint64_t Key 54 | mov %ecx, [%rdi + 16] 55 | mov %r8, [%rdi + 8] 56 | sub %rcx, 1 57 | jc .L5 58 | mov %rdi, [%rdi] 59 | mov %rax, %rsi 60 | shr %rax, INDEX_SHIFT 61 | and %rax, %rcx 62 | cmp %rsi, [%rdi + %rax * 8] 63 | je .L6 64 | ja .L5 65 | .L7: 66 | mov %rdx, %rsi 67 | shr %rdx, INCR_SHIFT 68 | or %rdx, 1 69 | .L8: 70 | add %rax, %rdx 71 | and %rax, %rcx 72 | cmp %rsi, [%rdi + %rax * 8] 73 | jb .L8 74 | ja .L5 75 | .L6: 76 | mov %rax, [%r8 + %rax * 8] 77 | xor %edx, %edx 78 | dec %rdx 79 | ret 80 | .L5: 81 | xor %eax, %eax 82 | xor %edx, %edx 83 | ret 84 | 85 | #ifdef __ELF__ 86 | .section .note.GNU-stack,"" 87 | #endif 88 | 89 | -------------------------------------------------------------------------------- /src/keywords.lst: -------------------------------------------------------------------------------- 1 | struct keyword_t {const char *Name; int Token;}; 2 | %% 3 | _, MLT_BLANK 4 | and, MLT_AND 5 | case, MLT_CASE 6 | def, MLT_DEF 7 | do, MLT_DO 8 | each, MLT_EACH 9 | else, MLT_ELSE 10 | elseif, MLT_ELSEIF 11 | end, MLT_END 12 | exit, MLT_EXIT 13 | for, MLT_FOR 14 | fun, MLT_FUN 15 | if, MLT_IF 16 | ifConfig, MLT_IF_CONFIG 17 | in, MLT_IN 18 | is, MLT_IS 19 | it, MLT_IT 20 | let, MLT_LET 21 | loop, MLT_LOOP 22 | meth, MLT_METH 23 | must, MLT_MUST 24 | next, MLT_NEXT 25 | nil, MLT_NIL 26 | not, MLT_NOT 27 | old, MLT_OLD 28 | on, MLT_ON 29 | or, MLT_OR 30 | recur, MLT_RECUR 31 | ref, MLT_REF 32 | ret, MLT_RET 33 | seq, MLT_SEQ 34 | susp, MLT_SUSP 35 | switch, MLT_SWITCH 36 | then, MLT_THEN 37 | to, MLT_TO 38 | until, MLT_UNTIL 39 | var, MLT_VAR 40 | when, MLT_WHEN 41 | while, MLT_WHILE 42 | with, MLT_WITH 43 | -------------------------------------------------------------------------------- /src/keywords.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | gperf -LANSI-C -C -c -t -KName -Zkeyword -Hhash -Nlookup -m 100 keywords.lst > keywords.c 3 | -------------------------------------------------------------------------------- /src/miniconsole: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S minilang -m gtk_console -------------------------------------------------------------------------------- /src/minidbg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S minilang 2 | let Console := import("gtk_console") 3 | let Buffer := string::buffer() 4 | Buffer:write('idebug("{string::escape(Args[1])}"') 5 | for Arg in Args skip 1 do 6 | Buffer:write(', \"{string::escape(Arg)}\"') 7 | end 8 | Buffer:write(")") 9 | Console:parser:input(Buffer:rest) 10 | Console:parser:evaluate(Console:compiler) -------------------------------------------------------------------------------- /src/minilang.h: -------------------------------------------------------------------------------- 1 | #ifndef MINILANG_H 2 | #define MINILANG_H 3 | 4 | #include 5 | #include 6 | 7 | #include "ml_compiler.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | extern stringmap_t MLGlobals[]; 14 | 15 | void ml_init(const char *ExecName, stringmap_t *Globals); 16 | 17 | #define MINILANG_VERSION 2, 12, 0 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/ml_ast.c: -------------------------------------------------------------------------------- 1 | #include "ml_compiler2.h" 2 | #include "ml_object.h" 3 | #include 4 | 5 | ml_value_t *mlc_expr_describe(mlc_expr_t *Expr); 6 | 7 | ML_ENUM2(ParamKindT, "param-kind", 8 | "Default", ML_PARAM_DEFAULT, 9 | "Extra", ML_PARAM_EXTRA, 10 | "Named", ML_PARAM_NAMED, 11 | "ByRef", ML_PARAM_BYREF, 12 | "AsVar", ML_PARAM_ASVAR 13 | ); 14 | 15 | ML_TYPE(AstNamesT, (MLListT), "ast::names"); 16 | 17 | static ml_value_t *ml_ast_names(ml_value_t *Value) { 18 | if (ml_typeof(Value) == MLNamesT) { 19 | ml_value_t *List = ml_list(); 20 | ML_NAMES_FOREACH(Value, Iter) ml_list_put(List, Iter->Value); 21 | List->Type = AstNamesT; 22 | return List; 23 | } else { 24 | return Value; 25 | } 26 | } 27 | 28 | #include "ml_ast_types.c" 29 | 30 | ML_METHOD("ast", MLExprT) { 31 | //ast::expr 33 | // Returns a tuple describing the expression :mini:`Expr`. 34 | return mlc_expr_describe((mlc_expr_t *)Args[0]); 35 | } 36 | 37 | void ml_ast_init(stringmap_t *Globals) { 38 | #include "ml_ast_init.c" 39 | ml_ast_types_init(); 40 | stringmap_insert(Ast->Exports, "names", AstNamesT); 41 | if (Globals) { 42 | stringmap_insert(Globals, "ast", Ast); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ml_ast.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_AST_H 2 | #define ML_AST_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_ast_init(stringmap_t *Globals); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/ml_base16.c: -------------------------------------------------------------------------------- 1 | #include "minilang.h" 2 | #include "ml_macros.h" 3 | 4 | #undef ML_CATEGORY 5 | #define ML_CATEGORY "base16" 6 | 7 | ML_FUNCTION(Base16Encode) { 8 | //@base16::encode 9 | //
string 11 | ML_CHECK_ARG_COUNT(1); 12 | ML_CHECK_ARG_TYPE(0, MLAddressT); 13 | static const unsigned char HexDigits[] = "0123456789ABCDEF"; 14 | size_t InSize = ml_address_length(Args[0]); 15 | size_t OutSize = 2 * InSize; 16 | const unsigned char *InChars = (const unsigned char *)ml_address_value(Args[0]); 17 | char *OutChars = snew(OutSize + 1), *Out = OutChars; 18 | for (int I = InSize; --I >= 0;) { 19 | unsigned char C = *InChars++; 20 | *Out++ = HexDigits[(C >> 4) & 15]; 21 | *Out++ = HexDigits[C & 15]; 22 | } 23 | *Out = 0; 24 | return ml_string(OutChars, OutSize); 25 | } 26 | 27 | ML_FUNCTION(Base16Decode) { 28 | //@base16::decode 29 | //address 31 | ML_CHECK_ARG_COUNT(1); 32 | ML_CHECK_ARG_TYPE(0, MLAddressT); 33 | size_t InSize = ml_address_length(Args[0]); 34 | size_t OutSize = (InSize + 1) / 2; 35 | const char *InChars = ml_address_value(Args[0]); 36 | char *OutChars = snew(OutSize + 1); 37 | unsigned char *Out = (unsigned char *)OutChars; 38 | int Odd = 1; 39 | for (int I = InSize; --I >= 0;) { 40 | unsigned char C = *InChars++; 41 | switch (C) { 42 | case 'a' ... 'f': C -= ('a' - 10); break; 43 | case 'A' ... 'F': C -= ('A' - 10); break; 44 | case '0' ... '9': C -= '0'; break; 45 | default: return ml_error("ValueError", "Invalid base 16 value"); 46 | } 47 | if (Odd) { 48 | *Out = C << 4; 49 | Odd = 0; 50 | } else { 51 | *Out++ += C; 52 | Odd = 1; 53 | } 54 | } 55 | if (!Odd) Out++; 56 | *Out = 0; 57 | return ml_address(OutChars, OutSize); 58 | } 59 | 60 | void ml_base16_init(stringmap_t *Globals) { 61 | #include "ml_base16_init.c" 62 | if (Globals) { 63 | stringmap_insert(Globals, "base16", ml_module("base16", 64 | "encode", Base16Encode, 65 | "decode", Base16Decode, 66 | NULL)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ml_base16.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_BASE16_H 2 | #define ML_BASE16_H 3 | 4 | #include "minilang.h" 5 | 6 | void ml_base16_init(stringmap_t *Globals); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/ml_base64.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_BASE64_H 2 | #define ML_BASE64_H 3 | 4 | #include "minilang.h" 5 | 6 | void ml_base64_init(stringmap_t *Globals); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/ml_bytecode.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_BYTECODE_H 2 | #define ML_BYTECODE_H 3 | 4 | #include "ml_types.h" 5 | #include "ml_runtime.h" 6 | #include "ml_opcodes.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | typedef struct ml_closure_t ml_closure_t; 13 | typedef struct ml_closure_info_t ml_closure_info_t; 14 | 15 | extern ml_type_t MLClosureT[]; 16 | extern ml_type_t MLClosureInfoT[]; 17 | 18 | typedef union ml_inst_t ml_inst_t; 19 | 20 | union ml_inst_t { 21 | struct { 22 | ml_opcode_t Opcode:8; 23 | unsigned int Reserved:8; 24 | unsigned int Label:16; 25 | unsigned int Line:32; 26 | }; 27 | ml_inst_t *Inst; 28 | ml_inst_t **Insts; 29 | int Count; 30 | ml_value_t *Value; 31 | ml_closure_info_t *ClosureInfo; 32 | ml_decl_t *Decls; 33 | const char *Chars; 34 | const char **Ptrs; 35 | void *Data; 36 | }; 37 | 38 | #define ML_CLOSURE_EXTRA_ARGS 1 39 | #define ML_CLOSURE_NAMED_ARGS 2 40 | #define ML_CLOSURE_RESERVED 4 41 | #define ML_CLOSURE_LABELLED 8 42 | #define ML_CLOSURE_HASHED 16 43 | 44 | struct ml_closure_info_t { 45 | ml_type_t *Type; 46 | ml_inst_t *Entry, *Return, *Halt; 47 | const char *Name, *Source; 48 | ml_decl_t *Decls; 49 | #ifdef ML_JIT 50 | void *JITStart, *JITEntry, *JITReturn; 51 | #endif 52 | stringmap_t Params[1]; 53 | int StartLine, EndLine, FrameSize; 54 | int NumParams, NumUpValues; 55 | int Flags; 56 | unsigned char Hash[SHA256_BLOCK_SIZE]; 57 | }; 58 | 59 | typedef struct ml_param_type_t ml_param_type_t; 60 | 61 | struct ml_param_type_t { 62 | ml_param_type_t *Next; 63 | ml_type_t *Type; 64 | int Index, HasDefault; 65 | }; 66 | 67 | ml_value_t *ml_closure(ml_closure_info_t *Info); 68 | 69 | void ml_closure_relax_names(ml_value_t *Closure); 70 | 71 | struct ml_closure_t { 72 | const ml_type_t *Type; 73 | const char *Name; 74 | ml_closure_info_t *Info; 75 | ml_param_type_t *ParamTypes; 76 | ml_value_t *UpValues[]; 77 | }; 78 | 79 | static inline stringmap_t *ml_closure_params(ml_value_t *Closure) { 80 | return ((ml_closure_t *)Closure)->Info->Params; 81 | } 82 | 83 | typedef struct ml_frame_t ml_frame_t; 84 | 85 | ml_value_t *ml_variable(ml_value_t *Value, ml_type_t *Type); 86 | ml_value_t *ml_variable_set(ml_value_t *Variable, ml_value_t *Value); 87 | 88 | extern ml_type_t MLVariableT[]; 89 | 90 | const char *ml_closure_debug(ml_value_t *Value); 91 | 92 | void ml_closure_info_labels(ml_closure_info_t *Info); 93 | //void ml_closure_info_list(ml_stringbuffer_t *Buffer, ml_closure_info_t *Info, int Indent); 94 | 95 | 96 | #ifdef ML_CBOR_BYTECODE 97 | 98 | #include "ml_cbor.h" 99 | 100 | void ml_cbor_write_closure(ml_closure_t *Closure, ml_stringbuffer_t *Buffer); 101 | 102 | ml_value_t *ml_cbor_read_closure(void *Data, int Count, ml_value_t **Args); 103 | 104 | #endif 105 | 106 | size_t ml_count_cached_frames(); 107 | 108 | void ml_bytecode_init(); 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/ml_bytecode_jit.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_BYTECODE_JIT_H 2 | #define ML_BYTECODE_JIT_H 3 | 4 | #include "ml_bytecode.h" 5 | 6 | void ml_bytecode_jit(ml_closure_info_t *Info); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/ml_console.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_CONSOLE_H 2 | #define ML_CONSOLE_H 3 | 4 | #include "minilang.h" 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | void ml_console(ml_context_t *Context, ml_getter_t GlobalGet, void *Globals, const char *DefaultPrompt, const char *ContinuePrompt); 12 | void ml_file_console(ml_context_t *Context, ml_getter_t GlobalGet, void *Globals, const char *DefaultPrompt, const char *ContinuePrompt, FILE *Input, FILE *Output); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/ml_coroutine.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_COROUTINE_H 2 | #define ML_COROUTINE_H 3 | 4 | #include "ml_types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_coro_enter(ml_state_t *Caller, ml_callback_t Function, int Count, ml_value_t **Args); 11 | 12 | ml_value_t *ml_coro_call(ml_value_t *Function, int Count, ml_value_t **Args); 13 | 14 | typedef struct ml_coro_state_t ml_coro_state_t; 15 | 16 | void *ml_coro_escape(void *Data, void (*Callback)(ml_coro_state_t *, void *)); 17 | 18 | void ml_coro_resume(ml_coro_state_t *State, void *Data); 19 | 20 | extern ml_type_t MLCoFunctionT[]; 21 | 22 | #define ML_COFUNCTION2(NAME, FUNCTION) static ml_value_t *FUNCTION(ml_state_t *State, int Count, ml_value_t **Args); \ 23 | \ 24 | ml_cfunction_t NAME[1] = {{MLCoFunctionT, FUNCTION, NULL}}; \ 25 | \ 26 | static ml_value_t *FUNCTION(ml_state_t *State, int Count, ml_value_t **Args) 27 | 28 | #define ML_COFUNCTION(NAME) ML_COFUNCTION2(NAME, CONCAT3(ml_cofunction_, __LINE__, __COUNTER__)) 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/ml_debugger.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUGGER_H 2 | #define DEBUGGER_H 3 | 4 | #include "stringmap.h" 5 | #include "ml_runtime.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef struct ml_interactive_debugger_t ml_interactive_debugger_t; 12 | 13 | ml_value_t *ml_interactive_debugger( 14 | void (*enter)(void *Data, ml_interactive_debugger_t *Debugger, ml_source_t Source, int Index), 15 | void (*exit)(void *Data, ml_interactive_debugger_t *Debugger, ml_state_t *Caller, int Index), 16 | void (*log)(void *Data, ml_value_t *Value), 17 | void *Data, 18 | ml_getter_t GlobalGet, 19 | void *Globals 20 | ) __attribute__ ((malloc)); 21 | 22 | ml_value_t *ml_interactive_debugger_get(ml_interactive_debugger_t *Debugger, const char *Name); 23 | ml_source_t ml_interactive_debugger_switch(ml_interactive_debugger_t *Debugger, int Index); 24 | void ml_interactive_debugger_resume(ml_interactive_debugger_t *Debugger, int Index); 25 | 26 | void ml_remote_debugger_init(ml_context_t *Context, const char *Address); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/ml_expr_types.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_EXPR_TYPES_H 2 | #define ML_EXPR_TYPES_H 3 | 4 | typedef enum { 5 | ML_EXPR_AND, 6 | ML_EXPR_ARGS, 7 | ML_EXPR_ASSIGN, 8 | ML_EXPR_BLANK, 9 | ML_EXPR_BLOCK, 10 | ML_EXPR_CALL, 11 | ML_EXPR_CONST_CALL, 12 | ML_EXPR_DEBUG, 13 | ML_EXPR_DEF, 14 | ML_EXPR_DEF_IN, 15 | ML_EXPR_DEF_UNPACK, 16 | ML_EXPR_DEFAULT, 17 | ML_EXPR_DEFINE, 18 | ML_EXPR_DELEGATE, 19 | ML_EXPR_EACH, 20 | ML_EXPR_EXIT, 21 | ML_EXPR_FOR, 22 | ML_EXPR_FUN, 23 | ML_EXPR_GUARD, 24 | ML_EXPR_IDENT, 25 | ML_EXPR_IF_CONFIG, 26 | ML_EXPR_IF, 27 | ML_EXPR_INLINE, 28 | ML_EXPR_IT, 29 | ML_EXPR_LET, 30 | ML_EXPR_LET_IN, 31 | ML_EXPR_LET_UNPACK, 32 | ML_EXPR_LIST, 33 | ML_EXPR_LOOP, 34 | ML_EXPR_MAP, 35 | ML_EXPR_NEXT, 36 | ML_EXPR_NIL, 37 | ML_EXPR_NOT, 38 | ML_EXPR_OLD, 39 | ML_EXPR_OR, 40 | ML_EXPR_RECUR, 41 | ML_EXPR_REF, 42 | ML_EXPR_REF_IN, 43 | ML_EXPR_REF_UNPACK, 44 | ML_EXPR_REGISTER, 45 | ML_EXPR_RESOLVE, 46 | ML_EXPR_RETURN, 47 | ML_EXPR_SCOPED, 48 | ML_EXPR_STRING, 49 | ML_EXPR_SUBST, 50 | ML_EXPR_SUSPEND, 51 | ML_EXPR_SWITCH, 52 | ML_EXPR_TUPLE, 53 | ML_EXPR_UNKNOWN, 54 | ML_EXPR_VALUE, 55 | ML_EXPR_VAR, 56 | ML_EXPR_VAR_IN, 57 | ML_EXPR_VAR_TYPE, 58 | ML_EXPR_VAR_UNPACK, 59 | ML_EXPR_WITH, 60 | } ml_expr_type_t; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/ml_file.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_FILE_H 2 | #define ML_FILE_H 3 | 4 | #include 5 | #include "minilang.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern ml_type_t MLFileT[]; 12 | 13 | void ml_file_init(stringmap_t *Globals); 14 | 15 | ml_value_t *ml_file(FILE *File); 16 | 17 | FILE *ml_file_handle(ml_value_t *Value) __attribute__((pure)); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/ml_json.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_JSON_H 2 | #define ML_JSON_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern ml_type_t MLJsonT[]; 11 | 12 | void ml_json_init(stringmap_t *Globals); 13 | 14 | ml_value_t *ml_json_decode(const char *Json, size_t Size); 15 | ml_value_t *ml_json_encode(ml_stringbuffer_t *Buffer, ml_value_t *Value); 16 | 17 | typedef struct json_decoder_t json_decoder_t; 18 | 19 | json_decoder_t *json_decoder(void (*emit)(json_decoder_t *Decoder, ml_value_t *Value), void *Data); 20 | void *json_decoder_data(json_decoder_t *Decoder); 21 | ml_value_t *json_decoder_parse(json_decoder_t *Decoder, const char *Input, size_t Size); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/ml_library.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_LIBRARY_H 2 | #define ML_LIBRARY_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_library_init(stringmap_t *Globals); 11 | 12 | void ml_library_path_add(const char *Path); 13 | void ml_library_loader_add( 14 | const char *Extension, int (*Test)(const char *), 15 | void (*Load)(ml_state_t *, const char *, ml_value_t **), 16 | ml_value_t *(*Load0)(const char *, ml_value_t **) 17 | ); 18 | 19 | ml_value_t *ml_library_importer(const char *FileName); 20 | 21 | void ml_library_load(ml_state_t *Caller, const char *Path, const char *Name); 22 | ml_value_t *ml_library_load0(const char *Path, const char *Name); 23 | 24 | void ml_library_register(const char *Name, ml_value_t *Module); 25 | ml_module_t *ml_library_internal(const char *Name); 26 | 27 | typedef void (*ml_library_entry_t)(ml_state_t *Caller, ml_value_t **Slot); 28 | typedef void (*ml_library_entry0_t)(ml_value_t **Slot); 29 | 30 | #define STRINGIFY(x) #x 31 | #define TOSTRING3(x, y, z) STRINGIFY(x ## y ## z) 32 | 33 | #define LIBRARY_ENTRY(NAME) TOSTRING3(ml_, NAME, _entry) 34 | #define LIBRARY_ENTRY0(NAME) TOSTRING3(ml_, NAME, _entry0) 35 | 36 | #ifdef __cplusplus 37 | #define ML_EXTERN extern "C" 38 | #else 39 | #define ML_EXTERN 40 | #endif 41 | 42 | #define ML_LIBRARY_ENTRY(NAME) \ 43 | ML_EXTERN void CONCAT3(ml_, NAME, entry)(ml_state_t *Caller, ml_value_t **Slot); \ 44 | ML_EXTERN void ml_library_entry(ml_state_t *Caller, ml_value_t **Slot) __attribute__ ((weak, alias(LIBRARY_ENTRY(NAME)))); \ 45 | void CONCAT3(ml_, NAME, entry)(ml_state_t *Caller, ml_value_t **Slot) 46 | 47 | #define ML_LIBRARY_ENTRY0(NAME) \ 48 | ML_EXTERN void CONCAT3(ml_, NAME, entry0)(ml_value_t **Slot); \ 49 | ML_EXTERN void ml_library_entry0(ml_value_t **Slot) __attribute__ ((weak, alias(LIBRARY_ENTRY0(NAME)))); \ 50 | void CONCAT3(ml_, NAME, entry0)(ml_value_t **Slot) 51 | 52 | typedef void (*ml_main_loop_t)(); 53 | 54 | #define ML_LIBRARY_SCHEDULER(NAME) \ 55 | ml_main_loop_t ml_library_scheduler_init(ml_context_t *Context) 56 | 57 | #define ML_LIBRARY_LOGGER(NAME) \ 58 | void ml_library_logger_init(ml_context_t *Context) 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/ml_logging.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_LOGGER_H 2 | #define ML_LOGGER_H 3 | 4 | /// \defgroup logging 5 | /// @{ 6 | /// 7 | 8 | #include "minilang.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef enum { 15 | ML_LOG_LEVEL_NONE = 0, 16 | ML_LOG_LEVEL_FATAL = 1, 17 | ML_LOG_LEVEL_ERROR = 2, 18 | ML_LOG_LEVEL_WARN = 3, 19 | ML_LOG_LEVEL_MESSAGE = 4, 20 | ML_LOG_LEVEL_INFO = 5, 21 | ML_LOG_LEVEL_DEBUG = 6, 22 | ML_LOG_LEVEL_ALL = 7 23 | } ml_log_level_t; 24 | 25 | typedef struct ml_logger_t ml_logger_t; 26 | 27 | struct ml_logger_t { 28 | ml_type_t *Type; 29 | const char *Name; 30 | const char *AnsiName; 31 | ml_value_t *Loggers[ML_LOG_LEVEL_ALL]; 32 | int Ignored[ML_LOG_LEVEL_ALL]; 33 | }; 34 | 35 | typedef void (*ml_logger_fn)(ml_logger_t *Logger, ml_log_level_t Level, ml_value_t *Error, const char *Source, int Line, const char *Format, ...) __attribute__((format(printf, 6, 7))); 36 | 37 | extern ml_log_level_t MLLogLevel; 38 | extern ml_logger_fn ml_log; 39 | extern ml_logger_t MLLoggerDefault[]; 40 | 41 | #ifndef ML_LOGGER 42 | #define ML_LOGGER MLLoggerDefault 43 | #endif 44 | 45 | #define ML_LOG_FATAL(ERROR, FORMAT, ...) \ 46 | if (MLLogLevel >= ML_LOG_LEVEL_FATAL) { \ 47 | ml_log(ML_LOGGER, ML_LOG_LEVEL_FATAL, ERROR, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__); \ 48 | } 49 | #define ML_LOG_ERROR(ERROR, FORMAT, ...) \ 50 | if (MLLogLevel >= ML_LOG_LEVEL_ERROR) { \ 51 | ml_log(ML_LOGGER, ML_LOG_LEVEL_ERROR, ERROR, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__); \ 52 | } 53 | #define ML_LOG_WARN(ERROR, FORMAT, ...) \ 54 | if (MLLogLevel >= ML_LOG_LEVEL_WARN) { \ 55 | ml_log(ML_LOGGER, ML_LOG_LEVEL_WARN, ERROR, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__); \ 56 | } 57 | #define ML_LOG_MESSAGE(ERROR, FORMAT, ...) \ 58 | if (MLLogLevel >= ML_LOG_LEVEL_MESSAGE) { \ 59 | ml_log(ML_LOGGER, ML_LOG_LEVEL_MESSAGE, ERROR, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__); \ 60 | } 61 | #define ML_LOG_INFO(ERROR, FORMAT, ...) \ 62 | if (MLLogLevel >= ML_LOG_LEVEL_INFO) { \ 63 | ml_log(ML_LOGGER, ML_LOG_LEVEL_INFO, ERROR, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__); \ 64 | } 65 | #define ML_LOG_DEBUG(ERROR, FORMAT, ...) \ 66 | if (MLLogLevel >= ML_LOG_LEVEL_DEBUG) { \ 67 | ml_log(ML_LOGGER, ML_LOG_LEVEL_DEBUG, ERROR, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__); \ 68 | } 69 | 70 | ml_logger_t *ml_logger(const char *Name); 71 | void ml_logger_init(ml_logger_t *Logger, const char *Name); 72 | 73 | void ml_logging_init(stringmap_t *Globals); 74 | 75 | typedef void (*ml_log_level_fn)(ml_log_level_t Level, void *Data); 76 | 77 | void ml_log_level_watch(ml_log_level_fn Fn, void *Data); 78 | void ml_log_level_set(ml_log_level_t Level); 79 | 80 | #ifdef __cplusplus 81 | } 82 | #endif 83 | 84 | /// @} 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/ml_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_MACROS_H 2 | #define ML_MACROS_H 3 | 4 | #include 5 | 6 | #define new(T) ((T *)GC_MALLOC(sizeof(T))) 7 | #define anew(T, N) ((T *)GC_MALLOC((N) * sizeof(T))) 8 | #define snew(N) ((char *)GC_MALLOC_ATOMIC(N)) 9 | #define asnew(T, N) ((T *)GC_MALLOC_ATOMIC((N) * sizeof(T))) 10 | #define bnew(N) GC_MALLOC(N) 11 | #define xnew(T, N, U) ((T *)GC_MALLOC(sizeof(T) + (N) * sizeof(U))) 12 | #define unew(T) ((T *)GC_MALLOC_UNCOLLECTABLE(sizeof(T))) 13 | 14 | #define PP_NARG(...) \ 15 | PP_NARG_(__VA_ARGS__,PP_RSEQ_N()) 16 | #define PP_NARG_(...) \ 17 | PP_ARG_N(__VA_ARGS__) 18 | #define PP_ARG_N( \ 19 | _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 20 | _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 21 | _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 22 | _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 23 | _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 24 | _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 25 | _61,_62,_63,N,...) N 26 | #define PP_RSEQ_N() \ 27 | 63,62,61,60, \ 28 | 59,58,57,56,55,54,53,52,51,50, \ 29 | 49,48,47,46,45,44,43,42,41,40, \ 30 | 39,38,37,36,35,34,33,32,31,30, \ 31 | 29,28,27,26,25,24,23,22,21,20, \ 32 | 19,18,17,16,15,14,13,12,11,10, \ 33 | 9,8,7,6,5,4,3,2,1,0 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/ml_math.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_MATH_H 2 | #define ML_MATH_H 3 | 4 | /// \defgroup math 5 | /// @{ 6 | /// 7 | 8 | #include "minilang.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | extern ml_value_t *AcosMethod; 15 | extern ml_value_t *AsinMethod; 16 | extern ml_value_t *AtanMethod; 17 | extern ml_value_t *CeilMethod; 18 | extern ml_value_t *CosMethod; 19 | extern ml_value_t *CoshMethod; 20 | extern ml_value_t *ExpMethod; 21 | extern ml_value_t *AbsMethod; 22 | extern ml_value_t *FloorMethod; 23 | extern ml_value_t *LogMethod; 24 | extern ml_value_t *Log10Method; 25 | extern ml_value_t *LogitMethod; 26 | extern ml_value_t *SinMethod; 27 | extern ml_value_t *SinhMethod; 28 | extern ml_value_t *SqrtMethod; 29 | extern ml_value_t *SquareMethod; 30 | extern ml_value_t *TanMethod; 31 | extern ml_value_t *TanhMethod; 32 | extern ml_value_t *ErfMethod; 33 | extern ml_value_t *ErfcMethod; 34 | extern ml_value_t *GammaMethod; 35 | extern ml_value_t *AcoshMethod; 36 | extern ml_value_t *AsinhMethod; 37 | extern ml_value_t *AtanhMethod; 38 | extern ml_value_t *CbrtMethod; 39 | extern ml_value_t *Expm1Method; 40 | extern ml_value_t *Log1pMethod; 41 | extern ml_value_t *RoundMethod; 42 | extern ml_value_t *ArgMethod; 43 | extern ml_value_t *ConjMethod; 44 | 45 | double logit(double X); 46 | 47 | void ml_math_init(stringmap_t *Globals); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | /// @} 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/ml_method.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_METHOD_H 2 | #define ML_METHOD_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_method_init(); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/ml_minijs.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_JSENCODE_H 2 | #define ML_JSENCODE_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef struct { 11 | ml_type_t *Type; 12 | ml_value_t *Value; 13 | } ml_minijs_t; 14 | 15 | extern ml_type_t MLMinijsT[]; 16 | 17 | typedef struct ml_minijs_encoder_t ml_minijs_encoder_t; 18 | 19 | struct ml_minijs_encoder_t { 20 | ml_externals_t *Externals; 21 | inthash_t Cached[1]; 22 | int LastIndex; 23 | }; 24 | 25 | ml_value_t *ml_minijs_encode(ml_minijs_encoder_t *Encoder, ml_value_t *Value); 26 | 27 | void ml_minijs_init(stringmap_t *Globals); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/ml_mmap.c: -------------------------------------------------------------------------------- 1 | #include "ml_mmap.h" 2 | #include "ml_macros.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | ML_TYPE(MLMMapT, (MLAddressT), "mmap"); 13 | 14 | ML_TYPE(MLMMapBufferT, (MLMMapT, MLBufferT), "mmap::buffer"); 15 | 16 | ML_METHOD(MLMMapT, MLStringT, MLStringT) { 17 | int OpenMode, MMapProtect; 18 | ml_type_t *Type; 19 | switch (ml_string_value(Args[1])[0]) { 20 | case 'r': 21 | OpenMode = O_RDONLY; 22 | MMapProtect = PROT_READ; 23 | Type = MLMMapT; 24 | break; 25 | case 'w': 26 | OpenMode = O_RDWR | O_CREAT; 27 | MMapProtect = PROT_READ | PROT_WRITE; 28 | Type = MLMMapBufferT; 29 | break; 30 | default: 31 | return ml_error("ValueError", "Invalid mode for mmap"); 32 | } 33 | const char *Path = ml_string_value(Args[0]); 34 | int Fd = open(ml_string_value(Args[0]), OpenMode, 0600); 35 | if (Fd < 0) return ml_error("FileError", "failed to map %s in mode %s: %s", Path, ml_string_value(Args[1]), strerror(errno)); 36 | struct stat Stat[1]; 37 | fstat(Fd, Stat); 38 | void *Ptr = mmap(NULL, Stat->st_size, MMapProtect, MAP_SHARED, Fd, 0); 39 | if (Ptr == MAP_FAILED) { 40 | close(Fd); 41 | return ml_error("MMapError", "failed to map %s in mode %s: %s", Path, ml_string_value(Args[1]), strerror(errno)); 42 | } 43 | close(Fd); 44 | ml_address_t *MMap = (ml_address_t *)ml_address(Ptr, Stat->st_size); 45 | MMap->Type = Type; 46 | return (ml_value_t *)MMap; 47 | } 48 | 49 | ML_METHOD("unmap", MLMMapT) { 50 | ml_address_t *MMap = (ml_address_t *)Args[0]; 51 | if (munmap(MMap->Value, MMap->Length) < 0) { 52 | return ml_error("MMapError", "failed to unmap: %s", strerror(errno)); 53 | } 54 | return MLNil; 55 | } 56 | 57 | void ml_mmap_init(stringmap_t *Globals) { 58 | #include "ml_mmap_init.c" 59 | stringmap_insert(MLMMapT->Exports, "buffer", MLMMapBufferT); 60 | if (Globals) { 61 | stringmap_insert(Globals, "mmap", MLMMapT); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/ml_mmap.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_MMAP_H 2 | #define ML_MMAP_H 3 | 4 | #include 5 | #include "minilang.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern ml_type_t MLMMapT[]; 12 | 13 | void ml_mmap_init(stringmap_t *Globals); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/ml_module.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_MODULE_H 2 | #define ML_MODULE_H 3 | 4 | #include "minilang.h" 5 | 6 | #define MLMF_USE_GLOBALS 1 7 | 8 | void ml_module_init(stringmap_t *Globals); 9 | 10 | void ml_module_compile(ml_state_t *Caller, const char *Path, const mlc_expr_t *Expr, ml_compiler_t *Compiler, ml_value_t **Slot); 11 | void ml_module_compile2(ml_state_t *Caller, const char *Path, const mlc_expr_t *Expr, ml_compiler_t *Compiler, ml_value_t **Slot, int Flags); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/ml_opcodes.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_OPCODES_H 2 | #define ML_OPCODES_H 3 | 4 | #define ML_BYTECODE_VERSION 5 5 | 6 | typedef enum { 7 | MLI_AND = 0, 8 | MLI_AND_POP = 1, 9 | MLI_ASSIGN = 2, 10 | MLI_ASSIGN_LOCAL = 3, 11 | MLI_CALL = 4, 12 | MLI_CALL_CONST = 5, 13 | MLI_CALL_METHOD = 6, 14 | MLI_CATCH = 7, 15 | MLI_CATCHX = 8, 16 | MLI_CLOSURE = 9, 17 | MLI_CLOSURE_TYPED = 10, 18 | MLI_ENTER = 11, 19 | MLI_EXIT = 12, 20 | MLI_FOR = 13, 21 | MLI_GOTO = 14, 22 | MLI_IF_CONFIG = 15, 23 | MLI_ITER = 16, 24 | MLI_KEY = 17, 25 | MLI_LET = 18, 26 | MLI_LETI = 19, 27 | MLI_LETX = 20, 28 | MLI_LINK = 21, 29 | MLI_LIST_APPEND = 22, 30 | MLI_LIST_NEW = 23, 31 | MLI_LOAD = 24, 32 | MLI_LOAD_PUSH = 25, 33 | MLI_LOAD_VAR = 26, 34 | MLI_LOCAL = 27, 35 | MLI_LOCALI = 28, 36 | MLI_LOCAL_PUSH = 29, 37 | MLI_MAP_INSERT = 30, 38 | MLI_MAP_NEW = 31, 39 | MLI_NEXT = 32, 40 | MLI_NIL = 33, 41 | MLI_NIL_PUSH = 34, 42 | MLI_NOT = 35, 43 | MLI_OR = 36, 44 | MLI_PARAM_TYPE = 37, 45 | MLI_PARTIAL_NEW = 38, 46 | MLI_PARTIAL_SET = 39, 47 | MLI_POP = 40, 48 | MLI_PUSH = 41, 49 | MLI_REF = 42, 50 | MLI_REFI = 43, 51 | MLI_REFX = 44, 52 | MLI_RESOLVE = 45, 53 | MLI_RESUME = 46, 54 | MLI_RETRY = 47, 55 | MLI_RETURN = 48, 56 | MLI_STRING_ADD = 49, 57 | MLI_STRING_ADDS = 50, 58 | MLI_STRING_ADD_1 = 51, 59 | MLI_STRING_END = 52, 60 | MLI_STRING_NEW = 53, 61 | MLI_STRING_POP = 54, 62 | MLI_SUSPEND = 55, 63 | MLI_SWITCH = 56, 64 | MLI_TAIL_CALL = 57, 65 | MLI_TAIL_CALL_CONST = 58, 66 | MLI_TAIL_CALL_METHOD = 59, 67 | MLI_TRY = 60, 68 | MLI_TUPLE_NEW = 61, 69 | MLI_UPVALUE = 62, 70 | MLI_VALUE_1 = 63, 71 | MLI_VALUE_2 = 64, 72 | MLI_VAR = 65, 73 | MLI_VARX = 66, 74 | MLI_VAR_TYPE = 67, 75 | MLI_WITH = 68, 76 | MLI_WITHX = 69, 77 | } ml_opcode_t; 78 | 79 | typedef enum { 80 | MLIT_CLOSURE, 81 | MLIT_COUNT, 82 | MLIT_COUNT_CHARS, 83 | MLIT_COUNT_COUNT, 84 | MLIT_COUNT_COUNT_DECL, 85 | MLIT_COUNT_DECL, 86 | MLIT_DECL, 87 | MLIT_INST, 88 | MLIT_INST_CONFIG, 89 | MLIT_INST_COUNT, 90 | MLIT_INST_COUNT_DECL, 91 | MLIT_NONE, 92 | MLIT_SWITCH, 93 | MLIT_VALUE, 94 | MLIT_VALUE_COUNT, 95 | MLIT_VALUE_COUNT_DATA, 96 | } ml_inst_type_t; 97 | 98 | extern const char *MLInstNames[]; 99 | extern const ml_inst_type_t MLInstTypes[]; 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/ml_polynomial.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_POLY_H 2 | #define ML_POLY_H 3 | 4 | #include "stringmap.h" 5 | #include "ml_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef struct { 12 | int Variable, Degree; 13 | } ml_factor_t; 14 | 15 | typedef struct { 16 | int Degree, Count; 17 | ml_factor_t Factors[]; 18 | } ml_factors_t; 19 | 20 | #ifdef ML_COMPLEX 21 | #include 22 | #undef I 23 | 24 | typedef complex double ml_coeff_t; 25 | 26 | #else 27 | 28 | typedef double ml_coeff_t; 29 | 30 | #endif 31 | 32 | typedef struct { 33 | const ml_factors_t *Factors; 34 | ml_coeff_t Coeff; 35 | } ml_term_t; 36 | 37 | typedef struct { 38 | ml_type_t *Type; 39 | int Count; 40 | ml_term_t Terms[]; 41 | } ml_polynomial_t; 42 | 43 | extern ml_type_t MLPolynomialT[]; 44 | 45 | typedef struct { 46 | ml_type_t *Type; 47 | ml_polynomial_t *A, *B; 48 | } ml_polynomial_rational_t; 49 | 50 | extern ml_type_t MLPolynomialRationalT[]; 51 | 52 | const char *ml_polynomial_name(int Index); 53 | 54 | void ml_polynomial_write(ml_stringbuffer_t *Buffer, ml_polynomial_t *Poly); 55 | 56 | void ml_polynomial_init(stringmap_t *Globals); 57 | 58 | #ifdef ML_COMPLEX 59 | 60 | void ml_roots_linear(const complex double C[], complex double R[]); 61 | void ml_roots_quadratic(const complex double C[], complex double R[]); 62 | void ml_roots_cubic(const complex double C[], complex double R[]); 63 | void ml_roots_quartic(const complex double C[], complex double R[]); 64 | void ml_roots_general(int N, const complex double C[], complex double R[]); 65 | 66 | #endif 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/ml_pqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_PQUEUE_H 2 | #define ML_PQUEUE_H 3 | 4 | #include "stringmap.h" 5 | #include "ml_types.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | ml_value_t *ml_pqueue(ml_value_t *Compare); 12 | 13 | void ml_pqueue_init(stringmap_t *Globals); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/ml_sequence.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_ITERFNS_H 2 | #define ML_ITERFNS_H 3 | 4 | #include "stringmap.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_sequence_init(stringmap_t *Globals); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/ml_socket.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_SOCKET_H 2 | #define ML_SOCKET_H 3 | 4 | #include 5 | #include "minilang.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern ml_type_t MLSocketT[]; 12 | 13 | void ml_socket_init(stringmap_t *Globals); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/ml_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_STREAM_H 2 | #define ML_STREAM_H 3 | 4 | /// \defgroup streams 5 | /// @{ 6 | /// 7 | 8 | #include "minilang.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | void ml_stream_init(stringmap_t *Globals); 15 | 16 | extern ml_type_t MLStreamT[]; 17 | 18 | void ml_stream_read(ml_state_t *Caller, ml_value_t *Value, void *Address, int Count); 19 | void ml_stream_write(ml_state_t *Caller, ml_value_t *Value, const void *Address, int Count); 20 | void ml_stream_flush(ml_state_t *Caller, ml_value_t *Value); 21 | void ml_stream_seek(ml_state_t *Caller, ml_value_t *Value, int64_t Offset, int Mode); 22 | void ml_stream_tell(ml_state_t *Caller, ml_value_t *Value); 23 | void ml_stream_close(ml_state_t *Caller, ml_value_t *Value); 24 | 25 | void ml_stream_read_method(ml_state_t *Caller, ml_value_t *Value, void *Address, int Count); 26 | void ml_stream_write_method(ml_state_t *Caller, ml_value_t *Value, const void *Address, int Count); 27 | void ml_stream_flush_method(ml_state_t *Caller, ml_value_t *Value); 28 | void ml_stream_seek_method(ml_state_t *Caller, ml_value_t *Value, int64_t Offset, int Mode); 29 | void ml_stream_tell_method(ml_state_t *Caller, ml_value_t *Value); 30 | void ml_stream_close_method(ml_state_t *Caller, ml_value_t *Value); 31 | 32 | ml_value_t *ml_stream_buffered(ml_value_t *Stream, size_t Size); 33 | 34 | extern ml_type_t MLStreamFdT[]; 35 | 36 | ml_value_t *ml_fd_stream(ml_type_t *Type, int Fd); 37 | int ml_fd_stream_fd(ml_value_t *Stream); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | /// @} 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/ml_table.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_TABLE_H 2 | #define ML_TABLE_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern ml_type_t MLTableT[]; 11 | 12 | void ml_table_init(stringmap_t *Globals); 13 | ml_value_t *ml_table(); 14 | ml_value_t *ml_table_insert(ml_value_t *Table, ml_value_t *Name, ml_value_t *Value); 15 | ml_value_t *ml_table_columns(ml_value_t *Table); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/ml_tasks.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_TASKS_H 2 | #define ML_TASKS_H 3 | 4 | #include "stringmap.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_tasks_init(stringmap_t *Globals); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/ml_thread.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_THREAD_H 2 | #define ML_THREAD_H 3 | 4 | #include "minilang.h" 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern ml_type_t MLThreadT[]; 12 | 13 | void ml_thread_init(stringmap_t *Globals); 14 | void ml_default_thread_init(ml_context_t *Context); 15 | ml_value_t *ml_is_threadsafe(ml_value_t *Value); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/ml_time.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_TIME_H 2 | #define ML_TIME_H 3 | 4 | #include "minilang.h" 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern ml_type_t MLTimeT[]; 12 | 13 | void ml_time_init(stringmap_t *Globals); 14 | ml_value_t *ml_time(time_t Sec, unsigned long NSec); 15 | ml_value_t *ml_time_parse(const char *Value, int Length); 16 | 17 | void ml_time_value(ml_value_t *Value, struct timespec *Time); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/ml_uuid.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_UUID_H 2 | #define ML_UUID_H 3 | 4 | #include "minilang.h" 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #ifndef UUID_STR_LEN 12 | #define UUID_STR_LEN 37 13 | #endif 14 | 15 | typedef struct { 16 | const ml_type_t *Type; 17 | uuid_t Value; 18 | } ml_uuid_t; 19 | 20 | extern ml_type_t MLUUIDT[]; 21 | 22 | void ml_uuid_init(stringmap_t *Globals); 23 | ml_value_t *ml_uuid(const uuid_t Value); 24 | ml_value_t *ml_uuid_parse(const char *Value, int Length); 25 | #define ml_uuid_value(UUID) ((ml_uuid_t *)UUID)->Value 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/ml_xe.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_XE_H 2 | #define ML_XE_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_xe_init(stringmap_t *Globals); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/ml_xml.h: -------------------------------------------------------------------------------- 1 | #ifndef ML_XML_H 2 | #define ML_XML_H 3 | 4 | #include "minilang.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void ml_xml_init(stringmap_t *Globals); 11 | 12 | extern ml_type_t MLXmlT[]; 13 | extern ml_type_t MLXmlTextT[]; 14 | extern ml_type_t MLXmlElementT[]; 15 | 16 | typedef struct ml_xml_node_t ml_xml_node_t; 17 | typedef struct ml_xml_element_t ml_xml_element_t; 18 | 19 | ml_xml_element_t *ml_xml_node_parent(ml_xml_node_t *Value); 20 | ml_xml_node_t *ml_xml_node_next(ml_xml_node_t *Value); 21 | ml_xml_node_t *ml_xml_node_prev(ml_xml_node_t *Value); 22 | 23 | ml_value_t *ml_xml_element_tag(ml_xml_element_t *Value); 24 | ml_value_t *ml_xml_element_attributes(ml_xml_element_t *Value); 25 | size_t ml_xml_element_length(ml_xml_element_t *Value); 26 | ml_xml_node_t *ml_xml_element_head(ml_xml_element_t *Value); 27 | 28 | ml_xml_element_t *ml_xml_element(const char *Tag); 29 | ml_xml_node_t *ml_xml_text(const char *Content, int Length); 30 | void ml_xml_element_put(ml_xml_element_t *Parent, ml_xml_node_t *Child); 31 | 32 | ml_value_t *ml_parser_escape_xml_like(ml_parser_t *Parser, ml_value_t *Constructor); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/opcodes.mini: -------------------------------------------------------------------------------- 1 | let Opcodes := [] 2 | 3 | let Version := with Input := file("opcodes.txt", "r") do 4 | let Version := Input:read:trim 5 | loop 6 | let Line := while Input:read 7 | Opcodes:put(Line:trim / ",") 8 | end 9 | Input:close 10 | Version 11 | end 12 | 13 | switch Args[1] or "c": string 14 | case "c" do 15 | with Output := file("ml_opcodes.h", "w") do 16 | Output:write("#ifndef ML_OPCODES_H\n#define ML_OPCODES_H\n\n") 17 | Output:write('#define ML_BYTECODE_VERSION {Version}\n\n') 18 | Output:write("typedef enum {\n") 19 | for I, (Name, Type) in Opcodes do 20 | Output:write('\tMLI_{Name} = {I - 1},\n') 21 | end 22 | Output:write("} ml_opcode_t;\n\ntypedef enum {\n") 23 | let Types := list(unique(Opcodes -> _[2])):sort 24 | for Type in Types do 25 | Output:write('\tMLIT_{Type},\n') 26 | end 27 | Output:write("} ml_inst_type_t;\n\nextern const char *MLInstNames[];\nextern const ml_inst_type_t MLInstTypes[];\n\n") 28 | Output:write("#endif\n") 29 | Output:close 30 | end 31 | 32 | with Output := file("ml_opcodes.c", "w") do 33 | Output:write("#include \"ml_opcodes.h\"\n\nconst char *MLInstNames[] = {\n") 34 | for (Name, Type) in Opcodes do 35 | Output:write('\t[MLI_{Name}] = \"{Name:lower}\",\n') 36 | end 37 | Output:write("};\n\nconst ml_inst_type_t MLInstTypes[] = {\n") 38 | for (Name, Type) in Opcodes do 39 | Output:write('\t[MLI_{Name}] = MLIT_{Type},\n') 40 | end 41 | Output:write("};\n\n") 42 | Output:close 43 | end 44 | case "js" do 45 | with Output := file("opcodes.js", "w") do 46 | Output:write('const ML_BYTECODE_VERSION = {Version};\n\n') 47 | for I, (Name, Type) in Opcodes do 48 | Output:write('const MLI_{Name} = {I - 1};\n') 49 | end 50 | Output:close 51 | end 52 | case "py" do 53 | with Output := file("opcodes.py", "w") do 54 | Output:write('ML_BYTECODE_VERSION = {Version}\n\n') 55 | for I, (Name, Type) in Opcodes do 56 | Output:write('MLI_{Name} = {I - 1}\n') 57 | end 58 | Output:close 59 | end 60 | case "java" do 61 | with Output := file("Opcode.java", "w") do 62 | Output:write("package wrapl.minilang;\n\n") 63 | Output:write("enum Opcode {") 64 | for I, (Name, Type) in Opcodes do 65 | I > 1 and Output:write(",") 66 | Output:write('\n\tMLI_{Name}') 67 | end 68 | Output:write("\n}\n") 69 | Output:close 70 | end 71 | end -------------------------------------------------------------------------------- /src/opcodes.txt: -------------------------------------------------------------------------------- 1 | 5 2 | AND,INST 3 | AND_POP,INST_COUNT 4 | ASSIGN,NONE 5 | ASSIGN_LOCAL,COUNT 6 | CALL,COUNT 7 | CALL_CONST,VALUE_COUNT 8 | CALL_METHOD,VALUE_COUNT_DATA 9 | CATCH,INST_COUNT_DECL 10 | CATCHX,INST_COUNT_DECL 11 | CLOSURE,CLOSURE 12 | CLOSURE_TYPED,CLOSURE 13 | ENTER,COUNT_COUNT_DECL 14 | EXIT,COUNT_DECL 15 | FOR,NONE 16 | GOTO,INST 17 | IF_CONFIG,INST_CONFIG 18 | ITER,INST 19 | KEY,NONE 20 | LET,COUNT 21 | LETI,COUNT 22 | LETX,COUNT_COUNT 23 | LINK,INST 24 | LIST_APPEND,NONE 25 | LIST_NEW,NONE 26 | LOAD,VALUE 27 | LOAD_PUSH,VALUE 28 | LOAD_VAR,VALUE_COUNT 29 | LOCAL,COUNT 30 | LOCALI,COUNT_DECL 31 | LOCAL_PUSH,COUNT 32 | MAP_INSERT,NONE 33 | MAP_NEW,NONE 34 | NEXT,INST 35 | NIL,NONE 36 | NIL_PUSH,NONE 37 | NOT,NONE 38 | OR,INST 39 | PARAM_TYPE,COUNT 40 | PARTIAL_NEW,COUNT 41 | PARTIAL_SET,COUNT 42 | POP,NONE 43 | PUSH,NONE 44 | REF,COUNT 45 | REFI,COUNT 46 | REFX,COUNT_COUNT 47 | RESOLVE,VALUE 48 | RESUME,NONE 49 | RETRY,NONE 50 | RETURN,NONE 51 | STRING_ADD,COUNT 52 | STRING_ADDS,COUNT_CHARS 53 | STRING_ADD_1,NONE 54 | STRING_END,NONE 55 | STRING_NEW,NONE 56 | STRING_POP,NONE 57 | SUSPEND,NONE 58 | SWITCH,SWITCH 59 | TAIL_CALL,COUNT 60 | TAIL_CALL_CONST,VALUE_COUNT 61 | TAIL_CALL_METHOD,VALUE_COUNT_DATA 62 | TRY,INST 63 | TUPLE_NEW,COUNT 64 | UPVALUE,COUNT 65 | VALUE_1,NONE 66 | VALUE_2,NONE 67 | VAR,COUNT 68 | VARX,COUNT_COUNT 69 | VAR_TYPE,COUNT 70 | WITH,DECL 71 | WITHX,COUNT_DECL -------------------------------------------------------------------------------- /src/sha256.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: sha256.h 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Defines the API for the corresponding SHA1 implementation. 7 | *********************************************************************/ 8 | 9 | #ifndef SHA256_H 10 | #define SHA256_H 11 | 12 | /*************************** HEADER FILES ***************************/ 13 | #include 14 | 15 | /****************************** MACROS ******************************/ 16 | #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 unsigned char digest 17 | 18 | /**************************** DATA TYPES ****************************/ 19 | 20 | typedef struct { 21 | unsigned char data[64]; 22 | unsigned int datalen; 23 | unsigned long long bitlen; 24 | unsigned int state[8]; 25 | } SHA256_CTX; 26 | 27 | /*********************** FUNCTION DECLARATIONS **********************/ 28 | void sha256_init(SHA256_CTX *ctx); 29 | void sha256_update(SHA256_CTX *ctx, const unsigned char data[], size_t len); 30 | void sha256_final(SHA256_CTX *ctx, unsigned char hash[]); 31 | 32 | #endif // SHA256_H 33 | -------------------------------------------------------------------------------- /src/stringmap.h: -------------------------------------------------------------------------------- 1 | #ifndef STRINGMAP_H 2 | #define STRINGMAP_H 3 | 4 | /// \defgroup stringmap 5 | /// @{ 6 | /// 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | typedef struct stringmap_t stringmap_t; 13 | typedef struct stringmap_node_t stringmap_node_t; 14 | 15 | struct stringmap_t { 16 | stringmap_node_t *Root; 17 | int Size; 18 | }; 19 | 20 | #define STRINGMAP_INIT {0,} 21 | 22 | stringmap_t *stringmap_new() __attribute__ ((malloc)); 23 | stringmap_t *stringmap_copy(stringmap_t *Map) __attribute__ ((malloc)); 24 | 25 | void *stringmap_search(const stringmap_t *Map, const char *Key) __attribute__ ((pure)); 26 | void *stringmap_insert(stringmap_t *Map, const char *Key, void *Value); 27 | void *stringmap_remove(stringmap_t *Map, const char *Key); 28 | void **stringmap_slot(stringmap_t *Map, const char *Key); 29 | int stringmap_foreach(stringmap_t *Map, void *Data, int (*callback)(const char *, void *, void *)); 30 | 31 | unsigned long stringmap_hash(const char *Key) __attribute__ ((pure)); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | /// @} 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/test/build.rabs: -------------------------------------------------------------------------------- 1 | fun test_minilang(Source) do 2 | var Target := meta('test-{Source:basename}')[MINILANG, Source] => fun() do 3 | var Actual := shell(MINILANG, Source) 4 | var File := (Source % "out"):open("r") 5 | var Expected := File:rest or "" 6 | File:close 7 | if Actual = Expected then 8 | print('\e[32mTest {Source:basename} passed!\e[0m\n') 9 | else 10 | print('\e[31mTest {Source:basename} failed.\e[0m\n') 11 | print('Expected {Expected:length} bytes:\n{Expected}\n---\n') 12 | print('Actual {Actual:length} bytes:\n{Actual}\n---\n') 13 | error("TestError", "Test failed") 14 | end 15 | end 16 | DEFAULT[Target] 17 | end 18 | 19 | for I in 1:up do 20 | let Test := file('test{I}.mini') 21 | while Test:exists 22 | test_minilang(Test) 23 | end 24 | 25 | MINILANG_CBOR and for I in 1:up do 26 | let Test := file('cbor_test{I}.mini') 27 | while Test:exists 28 | test_minilang(Test) 29 | end -------------------------------------------------------------------------------- /src/test/cbor_test1.mini: -------------------------------------------------------------------------------- 1 | let S := string::buffer() 2 | 3 | S:write("fun(X) X + {\n\t\"A1\" is 1") 4 | for I in 2 .. 100 do 5 | S:write(',\n\t\"A{I}\" is {I}') 6 | end 7 | S:write("\n}") 8 | 9 | let C := compiler(globals()) 10 | let P := parser() 11 | P:source("test", 1) 12 | P:input(S:rest) 13 | 14 | let F1 := P:compile(C)() 15 | 16 | let E := fmt::cbor::encode(F1) 17 | 18 | print(enc::base16::encode(E), "\n") 19 | 20 | let F2 := fmt::cbor::decode(E) 21 | 22 | print(F2({})) 23 | -------------------------------------------------------------------------------- /src/test/example1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static ml_value_t *print(void *Data, int Count, ml_value_t **Args) { 5 | ml_value_t *StringMethod = ml_method("string"); 6 | for (int I = 0; I < Count; ++I) { 7 | ml_value_t *Result = Args[I]; 8 | if (Result->Type != MLStringT) { 9 | Result = ml_call(StringMethod, 1, &Result); 10 | if (Result->Type == MLErrorT) return Result; 11 | if (Result->Type != MLStringT) return ml_error("ResultError", "string method did not return string"); 12 | } 13 | fwrite(ml_string_value(Result), 1, ml_string_length(Result), stdout); 14 | } 15 | fflush(stdout); 16 | return MLNil; 17 | } 18 | 19 | int main(int Argc, char **Argv) { 20 | ml_init(); 21 | stringmap_t *Globals = stringmap_new(); 22 | stringmap_insert(Globals, "print", ml_function(NULL, print)); 23 | ml_value_t *Value = ml_load_file((ml_getter_t)stringmap_search, Globals, "example1.mini"); 24 | if (Value->Type == MLErrorT) { 25 | ml_error_print(Value); 26 | exit(1); 27 | } 28 | Value = ml_call(Value, 0, NULL); 29 | if (Value->Type == MLErrorT) { 30 | ml_error_print(Value); 31 | exit(1); 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/example1.mini: -------------------------------------------------------------------------------- 1 | for X in 1 .. 10 do 2 | print('{X} ') 3 | end 4 | print('done.\n') -------------------------------------------------------------------------------- /src/test/libuv_test1.mini: -------------------------------------------------------------------------------- 1 | uv_run(;) do 2 | print("Hello world!\n") 3 | var File := uv_fs_open("test.txt", "r", 0) 4 | var Text := File:read(100) 5 | print('Text[{Text:length}] = {Text}\n') 6 | end 7 | -------------------------------------------------------------------------------- /src/test/libuv_test2.mini: -------------------------------------------------------------------------------- 1 | uv_run(;) do 2 | 3 | var Sum := 0 4 | for I in 1 .. 5 do 5 | var Wait := I * 11 % 7 6 | print('{I}: waiting {Wait} seconds.\n') 7 | uv_sleep(1000 * Wait) 8 | print('{I}: done.\n') 9 | Sum := old + 1 10 | end 11 | print('Done: Sum = {Sum}\n') 12 | 13 | Sum := 0 14 | parallel(1 .. 5; I) do 15 | var Wait := I * 11 % 7 16 | print('{I}: waiting {Wait} seconds.\n') 17 | uv_sleep(1000 * Wait) 18 | print('{I}: done.\n') 19 | Sum := old + 1 20 | end 21 | print('Done: Sum = {Sum}\n') 22 | 23 | end 24 | -------------------------------------------------------------------------------- /src/test/libuv_test3.mini: -------------------------------------------------------------------------------- 1 | uv_run(;) do 2 | 3 | var Sum := 0 4 | var Tasks := tasks() 5 | for I in 1 .. 5 do 6 | Tasks(;) do 7 | var Wait := I * 11 % 7 8 | print('{I}: waiting {Wait} seconds.\n') 9 | uv_sleep(1000 * Wait) 10 | print('{I}: done.\n') 11 | Sum := old + 1 12 | for J in 1 .. 3 do 13 | Tasks(;) do 14 | uv_sleep(1000 * J) 15 | print('{I}[{J}]: done\n') 16 | Sum := old + 1 17 | end 18 | end 19 | end 20 | end 21 | Tasks:wait 22 | print('Done: Sum = {Sum}\n') 23 | 24 | end 25 | -------------------------------------------------------------------------------- /src/test/libuv_test4.mini: -------------------------------------------------------------------------------- 1 | def uv := import("lib/ml_libuv.so") 2 | 3 | let Threads := all('\e[{N}m{N}\e[0m' for N in 30 .. 36) 4 | 5 | print("Without scheduler:\n") 6 | 7 | parallel(0 .. 14; N, I) do 8 | for J in 1 .. 30 do 9 | print('\e[48;5;{I}m[{I}, {J}]\e[0m') 10 | end 11 | end 12 | 13 | print("\n\n\nWith scheduler:\n") 14 | 15 | uv::run(;) do 16 | 17 | parallel(0 .. 14, 4, 2; N, I) do 18 | for J in 1 .. 30 do 19 | print('\e[48;5;{I}m[{I}, {J}]\e[0m') 20 | end 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /src/test/libuv_test5.mini: -------------------------------------------------------------------------------- 1 | def uv := import("lib/ml_libuv.so") 2 | 3 | uv::run(;) do 4 | 5 | var Sum := 0 6 | parallel(1 .. 100, 5, 10; I) do 7 | :>for I in 1 .. 100 do 8 | var Wait := I * 111 % 31 9 | print('{I}: waiting {Wait / 100.0} seconds.\n') 10 | uv::sleep(10 * Wait) 11 | print('{I}: done.\n') 12 | Sum := old + Wait 13 | end 14 | print('Done: Sum = {Sum}\n') 15 | 16 | end 17 | -------------------------------------------------------------------------------- /src/test/libuv_test6.mini: -------------------------------------------------------------------------------- 1 | def uv := import("lib/ml_libuv.so") 2 | 3 | uv::run(;) do 4 | 5 | var Sum := 0 6 | var Tasks := tasks(5, 10) 7 | 8 | for I in 1 .. 100 do 9 | Tasks:add(;) do 10 | var Wait := I * 111 % 31 11 | print('{I}: waiting {Wait / 100.0} seconds.\n') 12 | uv::sleep(10 * Wait) 13 | print('{I}: done.\n') 14 | Sum := old + Wait 15 | if I = 50 then 16 | Tasks:add(;) do 17 | print('Adding extra task at {I}!\n') 18 | uv::sleep(100) 19 | print('Extra task done!\n') 20 | end 21 | end 22 | end 23 | end 24 | 25 | Tasks:wait 26 | 27 | print('Done: Sum = {Sum}\n') 28 | 29 | end 30 | -------------------------------------------------------------------------------- /src/test/speed_test.mini: -------------------------------------------------------------------------------- 1 | let Count := integer(Args[1] or error("ArgError", "Count required")) 2 | 3 | fun fact(N) do 4 | if N <= 1 then 5 | ret 1 6 | else 7 | ret N * fact(N - 1) 8 | end 9 | end 10 | 11 | print('20! = {fact(20)}\n') 12 | 13 | let Start := clock() 14 | for I in 1 .. Count do 15 | fact(20) 16 | end 17 | print('Time taken = {clock() - Start}\n') 18 | -------------------------------------------------------------------------------- /src/test/speed_test2.mini: -------------------------------------------------------------------------------- 1 | let Count := integer(Args[1] or error("ArgError", "Count required")) 2 | 3 | fun fact(N) do 4 | var F := 1 5 | for I in 1 .. N do 6 | F := old * I 7 | end 8 | ret F 9 | end 10 | 11 | print('20! = {fact(20)}\n') 12 | 13 | let Start := clock() 14 | for I in 1 .. Count do 15 | fact(20) 16 | end 17 | print('Time taken = {clock() - Start}\n') 18 | -------------------------------------------------------------------------------- /src/test/test1.mini: -------------------------------------------------------------------------------- 1 | print("Hello world!") -------------------------------------------------------------------------------- /src/test/test1.out: -------------------------------------------------------------------------------- 1 | Hello world! -------------------------------------------------------------------------------- /src/test/test1.pp: -------------------------------------------------------------------------------- 1 | \fun bold(Text) write('*{Text}*'); 2 | Hello \bold("world");! Goodbye \bold("world");! 3 | \include("test2.pp"); Some words after the include. 4 | -------------------------------------------------------------------------------- /src/test/test10.mini: -------------------------------------------------------------------------------- 1 | class: point(:X, :Y) 2 | 3 | var A := point(10, 20) 4 | 5 | print('A:X = {A:X}\n') 6 | print('A = {A}\n') 7 | 8 | A:Y := 200 9 | 10 | meth :append(B: string::buffer, P: point) B:write('point({P:X}, {P:Y})') 11 | 12 | print('A = {A}\n') 13 | 14 | meth +(A: point, B: point) point(A:X + B:X, A:Y + B:Y) 15 | 16 | var B := point(23, 9.1) 17 | 18 | print('{A} + {B} = {A + B}\n') 19 | 20 | meth *(A: point, N: number) point(A:X * N, A:Y * N) 21 | meth *(N: number, A: point) point(N * A:X, N * A:Y) 22 | 23 | print('{A} * 5 = {A * 5}\n') 24 | print('7.1 * {B} = {7.1 * B}\n') 25 | 26 | class: vector(point, :Z) 27 | 28 | var C := vector(1, 2, 3) 29 | 30 | print('C = {C}\n') 31 | 32 | meth :append(B: string::buffer, V: vector) B:write('vector({V:X}, {V:Y}, {V:Z})') 33 | 34 | print('C = {C}\n') 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/test/test10.out: -------------------------------------------------------------------------------- 1 | A:X = 10 2 | A = point(X is 10, Y is 20) 3 | A = point(10, 200) 4 | point(10, 200) + point(23, 9.1) = point(33, 209.1) 5 | point(10, 200) * 5 = point(50, 1000) 6 | 7.1 * point(23, 9.1) = point(163.3, 64.61) 7 | C = point(1, 2) 8 | C = vector(1, 2, 3) 9 | -------------------------------------------------------------------------------- /src/test/test11.mini: -------------------------------------------------------------------------------- 1 | fun test(N) do 2 | for I in 1 .. N do 3 | susp I, I * I 4 | end 5 | end 6 | 7 | var T := {} 8 | 9 | for K, V in test $! [10] do 10 | print('{K} -> {V}\n') 11 | end 12 | -------------------------------------------------------------------------------- /src/test/test11.out: -------------------------------------------------------------------------------- 1 | 1 -> 1 2 | 2 -> 4 3 | 3 -> 9 4 | 4 -> 16 5 | 5 -> 25 6 | 6 -> 36 7 | 7 -> 49 8 | 8 -> 64 9 | 9 -> 81 10 | 10 -> 100 11 | -------------------------------------------------------------------------------- /src/test/test12.mini: -------------------------------------------------------------------------------- 1 | fun fibonacci(N) do 2 | if N <= 0 then 3 | error("RangeError", "N must be postive") 4 | elseif N <= 2 then 5 | ret 1 6 | end 7 | var A := 1, B := 1 8 | for I in 1 .. (N - 2) do 9 | var C := A + B 10 | A := B 11 | B := C 12 | end 13 | ret B 14 | end 15 | 16 | for I in 1 .. 10 do 17 | print('fibonacci({I}) = {fibonacci(I)}\n') 18 | end 19 | 20 | do 21 | print('fibonacci({0}) = {fibonacci(0)}\n') 22 | on Error do 23 | print('{Error:type}: {Error:message}\n') 24 | end 25 | -------------------------------------------------------------------------------- /src/test/test12.out: -------------------------------------------------------------------------------- 1 | fibonacci(1) = 1 2 | fibonacci(2) = 1 3 | fibonacci(3) = 2 4 | fibonacci(4) = 3 5 | fibonacci(5) = 5 6 | fibonacci(6) = 8 7 | fibonacci(7) = 13 8 | fibonacci(8) = 21 9 | fibonacci(9) = 34 10 | fibonacci(10) = 55 11 | RangeError: N must be postive 12 | -------------------------------------------------------------------------------- /src/test/test13.mini: -------------------------------------------------------------------------------- 1 | print('X 2 | 100 3 | 200\n') 4 | 5 | print('X\ 6 | 100 7 | 200\n') 8 | 9 | print('\ 10 | 100 11 | ':length) 12 | 13 | print('\ 14 | X = 100 15 | X = 110 16 | ':length) -------------------------------------------------------------------------------- /src/test/test13.out: -------------------------------------------------------------------------------- 1 | X 2 | 100 3 | 200 4 | X100 5 | 200 6 | 416 -------------------------------------------------------------------------------- /src/test/test14.mini: -------------------------------------------------------------------------------- 1 | print('Args = {Args}\n') 2 | -------------------------------------------------------------------------------- /src/test/test14.out: -------------------------------------------------------------------------------- 1 | Args = [] 2 | -------------------------------------------------------------------------------- /src/test/test15.mini: -------------------------------------------------------------------------------- 1 | def X := 100 + 200 2 | 3 | def Y := X + 20 4 | 5 | print('X = {X}\n') 6 | print('Y = {Y}\n') 7 | 8 | print('Test = {:([1, 2, 3, 4])}\n') 9 | -------------------------------------------------------------------------------- /src/test/test15.out: -------------------------------------------------------------------------------- 1 | X = 300 2 | Y = 320 3 | Test = [1, 2, 3, 4] 4 | -------------------------------------------------------------------------------- /src/test/test16.mini: -------------------------------------------------------------------------------- 1 | fun f1(X) do 2 | print('f1({X})\n') 3 | if X = 1 then 4 | 1 5 | elseif X % 2 = 0 then 6 | f1(X / 2) 7 | else 8 | f2(X) 9 | end 10 | end 11 | 12 | fun f2(X) do 13 | print('f2({X})\n') 14 | if X = 1 then 15 | 1 16 | elseif X % 2 = 0 then 17 | f1(X) 18 | else 19 | f2(3 * X + 1) 20 | end 21 | end 22 | 23 | print('f1(123) = {f1(1234)}\n') 24 | -------------------------------------------------------------------------------- /src/test/test17.mini: -------------------------------------------------------------------------------- 1 | with (A, B, C) := (1, 2, 3) do 2 | print('A = {A}, B = {B}, C = {C}\n') 3 | end 4 | 5 | let L := list(1 .. 100) 6 | 7 | for I in 1 .. 20 do 8 | print('L[{I}] := {L[I]}\n') 9 | end 10 | 11 | var N := 17 12 | for I in 1 .. 20 do 13 | print('L[{N}] := {L[N]}\n') 14 | N := old * 79 % 100 + 1 15 | end 16 | 17 | let M := list(zip(1 .. 20, "Hello world", tuple)) 18 | 19 | for I, (J, K) in M do 20 | print('I = {I}, J = {J}, K = {K}\n') 21 | end -------------------------------------------------------------------------------- /src/test/test17.out: -------------------------------------------------------------------------------- 1 | A = 1, B = 2, C = 3 2 | L[1] := 1 3 | L[2] := 2 4 | L[3] := 3 5 | L[4] := 4 6 | L[5] := 5 7 | L[6] := 6 8 | L[7] := 7 9 | L[8] := 8 10 | L[9] := 9 11 | L[10] := 10 12 | L[11] := 11 13 | L[12] := 12 14 | L[13] := 13 15 | L[14] := 14 16 | L[15] := 15 17 | L[16] := 16 18 | L[17] := 17 19 | L[18] := 18 20 | L[19] := 19 21 | L[20] := 20 22 | L[17] := 17 23 | L[44] := 44 24 | L[77] := 77 25 | L[84] := 84 26 | L[37] := 37 27 | L[24] := 24 28 | L[97] := 97 29 | L[64] := 64 30 | L[57] := 57 31 | L[4] := 4 32 | L[17] := 17 33 | L[44] := 44 34 | L[77] := 77 35 | L[84] := 84 36 | L[37] := 37 37 | L[24] := 24 38 | L[97] := 97 39 | L[64] := 64 40 | L[57] := 57 41 | L[4] := 4 42 | I = 1, J = 1, K = H 43 | I = 2, J = 2, K = e 44 | I = 3, J = 3, K = l 45 | I = 4, J = 4, K = l 46 | I = 5, J = 5, K = o 47 | I = 6, J = 6, K = 48 | I = 7, J = 7, K = w 49 | I = 8, J = 8, K = o 50 | I = 9, J = 9, K = r 51 | I = 10, J = 10, K = l 52 | I = 11, J = 11, K = d 53 | -------------------------------------------------------------------------------- /src/test/test18.mini: -------------------------------------------------------------------------------- 1 | let S := 'Minilang is a small imperative language, designed to be embedded into programs written in C. It has the following goals / features: 2 | 3 | Minimal dependencies 4 | 5 | Minilang has no dependencies other than the Hans Boehm garbage collector, and standard C libraries. 6 | Full Closures 7 | 8 | Functions in Minilang automatically capture their environment, creating closures at runtime. Closures can be passed around as first-class values, which are used to build targets in Rabs. 9 | Dynamic scoping 10 | 11 | The Minilang interpreter provides a callback for identifier resolution, allowing programs to provide dynamic scoping. This is used within Rabs to provide dynamic symbol resolution. 12 | Easy to embed & extend 13 | 14 | Minilang provides a comprehensive embedding API to support a wider range of use cases. It is easy to create new functions in C to use in Minilang.' 15 | 16 | print(S, "\n\n -> \n\n") 17 | 18 | print(S:replace({ 19 | "Minilang" is "MINILANG", 20 | r"pro([a-z]+) " is fun(S, [P]) 'PRO<{P[1]}> ' 21 | }), "\n") 22 | -------------------------------------------------------------------------------- /src/test/test18.out: -------------------------------------------------------------------------------- 1 | Minilang is a small imperative language, designed to be embedded into programs written in C. It has the following goals / features: 2 | 3 | Minimal dependencies 4 | 5 | Minilang has no dependencies other than the Hans Boehm garbage collector, and standard C libraries. 6 | Full Closures 7 | 8 | Functions in Minilang automatically capture their environment, creating closures at runtime. Closures can be passed around as first-class values, which are used to build targets in Rabs. 9 | Dynamic scoping 10 | 11 | The Minilang interpreter provides a callback for identifier resolution, allowing programs to provide dynamic scoping. This is used within Rabs to provide dynamic symbol resolution. 12 | Easy to embed & extend 13 | 14 | Minilang provides a comprehensive embedding API to support a wider range of use cases. It is easy to create new functions in C to use in Minilang. 15 | 16 | -> 17 | 18 | MINILANG is a small imperative language, designed to be embedded into PRO written in C. It has the following goals / features: 19 | 20 | Minimal dependencies 21 | 22 | MINILANG has no dependencies other than the Hans Boehm garbage collector, and standard C libraries. 23 | Full Closures 24 | 25 | Functions in MINILANG automatically capture their environment, creating closures at runtime. Closures can be passed around as first-class values, which are used to build targets in Rabs. 26 | Dynamic scoping 27 | 28 | The MINILANG interpreter PRO a callback for identifier resolution, allowing PRO to PRO dynamic scoping. This is used within Rabs to PRO dynamic symbol resolution. 29 | Easy to embed & extend 30 | 31 | MINILANG PRO a comprehensive embedding API to support a wider range of use cases. It is easy to create new functions in C to use in MINILANG. 32 | -------------------------------------------------------------------------------- /src/test/test19.mini: -------------------------------------------------------------------------------- 1 | print('', 'Hello', ' world!\n') 2 | print('Hello 3 | \tworld!') 4 | let X := 10 5 | print('X = {X}, Y = {27, 3}, Z = {2 + 2}\nL = {list(1 .. 10), ':'}') 6 | print('\n') -------------------------------------------------------------------------------- /src/test/test19.out: -------------------------------------------------------------------------------- 1 | Hello world! 2 | Hello 3 | world!X = 10, Y = 1000, Z = 4 4 | L = 1:2:3:4:5:6:7:8:9:10 5 | -------------------------------------------------------------------------------- /src/test/test2.mini: -------------------------------------------------------------------------------- 1 | var X := 100 2 | 3 | print('X = {X}\n') 4 | 5 | X := old + 10 6 | 7 | print('X = {X}\n') 8 | -------------------------------------------------------------------------------- /src/test/test2.out: -------------------------------------------------------------------------------- 1 | X = 100 2 | X = 110 3 | -------------------------------------------------------------------------------- /src/test/test2.pp: -------------------------------------------------------------------------------- 1 | Some random include file. 2 | Blah blah blah. -------------------------------------------------------------------------------- /src/test/test20.mini: -------------------------------------------------------------------------------- 1 | fun test(X) do 2 | if not X then 3 | "" 4 | elseif X in string or X in list then 5 | "" 6 | elseif X = 100 or X = 50 or X > 200 then 7 | "100 50, or > 200" 8 | elseif X between (60 .. 70) then 9 | "60 .. 70" 10 | else 11 | "" 12 | end 13 | end 14 | 15 | for X in [nil, "hello", [], 1, 50, 100, 200, 201, 65] do 16 | print('test({X}) -> {test(X)}\n') 17 | end 18 | -------------------------------------------------------------------------------- /src/test/test20.out: -------------------------------------------------------------------------------- 1 | test(nil) -> 2 | test(hello) -> 3 | test([]) -> 4 | test(1) -> 5 | test(50) -> 100 50, or > 200 6 | test(100) -> 100 50, or > 200 7 | test(200) -> 8 | test(201) -> 100 50, or > 200 9 | test(65) -> 60 .. 70 10 | -------------------------------------------------------------------------------- /src/test/test21.mini: -------------------------------------------------------------------------------- 1 | fun test_defs() do 2 | def M := map(V to K for K, V in "ABCDEF") 3 | def (A, B) in M 4 | def (C, D) := (3, 4) 5 | print('A = {A}, B = {B}, C = {C}, D = {D}\n') 6 | end 7 | 8 | fun test_lets() do 9 | let M := map(V to K for K, V in "ABCDEF") 10 | let (A, B) in M 11 | let (C, D) := (3, 4) 12 | print('A = {A}, B = {B}, C = {C}, D = {D}\n') 13 | end 14 | 15 | fun test_vars() do 16 | var M := map(V to K for K, V in "ABCDEF") 17 | var (A, B) in M 18 | var (C, D) := (3, 4) 19 | print('A = {A}, B = {B}, C = {C}, D = {D}\n') 20 | end 21 | 22 | test_defs() 23 | test_lets() 24 | test_vars() 25 | -------------------------------------------------------------------------------- /src/test/test21.out: -------------------------------------------------------------------------------- 1 | A = 1, B = 2, C = 3, D = 4 2 | A = 1, B = 2, C = 3, D = 4 3 | A = 1, B = 2, C = 3, D = 4 4 | -------------------------------------------------------------------------------- /src/test/test22.mini: -------------------------------------------------------------------------------- 1 | var L, S, R 2 | 3 | L := list(1 .. 10) 4 | S := [] 5 | R := L:splice(3, 4, S) 6 | print('L = {L}\n') 7 | print('S = {S}\n') 8 | print('R = {R}\n') 9 | 10 | L := list(1 .. 10) 11 | S := ["A", "B", "C"] 12 | R := L:splice(3, 4, S) 13 | print('L = {L}\n') 14 | print('S = {S}\n') 15 | print('R = {R}\n') 16 | 17 | L := list(1 .. 10) 18 | S := ["A", "B", "C"] 19 | R := L:splice(1, 4, S) 20 | print('L = {L}\n') 21 | print('S = {S}\n') 22 | print('R = {R}\n') 23 | 24 | L := list(1 .. 10) 25 | S := ["A", "B", "C"] 26 | R := L:splice(7, 4, S) 27 | print('L = {L}\n') 28 | print('S = {S}\n') 29 | print('R = {R}\n') 30 | 31 | L := list(1 .. 10) 32 | S := ["A", "B", "C"] 33 | R := L:splice(5, S) 34 | print('L = {L}\n') 35 | print('S = {S}\n') 36 | print('R = {R}\n') 37 | 38 | L := list(1 .. 10) 39 | S := ["A", "B", "C"] 40 | R := L:splice(1, 0, S) 41 | print('L = {L}\n') 42 | print('S = {S}\n') 43 | print('R = {R}\n') 44 | 45 | L := list(1 .. 10) 46 | S := ["A", "B", "C"] 47 | R := L:splice(10, 0, S) 48 | print('L = {L}\n') 49 | print('S = {S}\n') 50 | print('R = {R}\n') 51 | 52 | L := list(1 .. 10) 53 | S := ["A", "B", "C"] 54 | R := L:splice(0, 0, S) 55 | print('L = {L}\n') 56 | print('S = {S}\n') 57 | print('R = {R}\n') 58 | 59 | L := list(1 .. 10) 60 | S := ["A", "B", "C"] 61 | R := L:splice(11, 0, S) 62 | print('L = {L}\n') 63 | print('S = {S}\n') 64 | print('R = {R}\n') 65 | 66 | L := list(1 .. 10) 67 | S := ["A", "B", "C"] 68 | R := L:splice(12, 0, S) 69 | print('L = {L}\n') 70 | print('S = {S}\n') 71 | print('R = {R}\n') -------------------------------------------------------------------------------- /src/test/test22.out: -------------------------------------------------------------------------------- 1 | L = [1, 2, 7, 8, 9, 10] 2 | S = [] 3 | R = [3, 4, 5, 6] 4 | L = [1, 2, A, B, C, 7, 8, 9, 10] 5 | S = [] 6 | R = [3, 4, 5, 6] 7 | L = [A, B, C, 5, 6, 7, 8, 9, 10] 8 | S = [] 9 | R = [1, 2, 3, 4] 10 | L = [1, 2, 3, 4, 5, 6, A, B, C] 11 | S = [] 12 | R = [7, 8, 9, 10] 13 | L = [1, 2, 3, 4, A, B, C, 5, 6, 7, 8, 9, 10] 14 | S = [] 15 | R = [] 16 | L = [A, B, C, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 17 | S = [] 18 | R = [] 19 | L = [1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, 10] 20 | S = [] 21 | R = [] 22 | L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, A, B, C] 23 | S = [] 24 | R = [] 25 | L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, A, B, C] 26 | S = [] 27 | R = [] 28 | L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 29 | S = [A, B, C] 30 | R = nil 31 | -------------------------------------------------------------------------------- /src/test/test23.mini: -------------------------------------------------------------------------------- 1 | fun test(N) do 2 | print(switch N 3 | case "One" 4 | case "Two" 5 | case "Three" 6 | else error("CaseError", "Case outside range") 7 | end, "\n") 8 | end 9 | 10 | for I in 0 .. 3 do 11 | test(I) 12 | on Error do 13 | print('Error: {Error:message}\n') 14 | end 15 | 16 | fun test2(N) do 17 | print(switch N 18 | case "One" 19 | case "Two" 20 | case "Three" 21 | else "Else" 22 | end, "\n") 23 | end 24 | 25 | for I in 0 .. 4 do 26 | test2(I) 27 | on Error do 28 | print('Error: {Error:message}\n') 29 | end -------------------------------------------------------------------------------- /src/test/test23.out: -------------------------------------------------------------------------------- 1 | One 2 | Two 3 | Three 4 | Error: Case outside range 5 | One 6 | Two 7 | Three 8 | Else 9 | Else 10 | -------------------------------------------------------------------------------- /src/test/test24.mini: -------------------------------------------------------------------------------- 1 | fun test(N) do 2 | switch N: integer 3 | case 1 do "One" 4 | case 20 do "Twenty" 5 | case 3 .. 6 do "Few" 6 | case 7, 8 do "Several" 7 | else "Other" 8 | end 9 | end 10 | 11 | for I in 0 .. 25 do 12 | print('{I} -> {test(I)}\n') 13 | end -------------------------------------------------------------------------------- /src/test/test24.out: -------------------------------------------------------------------------------- 1 | 0 -> Other 2 | 1 -> One 3 | 2 -> Other 4 | 3 -> Few 5 | 4 -> Few 6 | 5 -> Few 7 | 6 -> Few 8 | 7 -> Several 9 | 8 -> Several 10 | 9 -> Other 11 | 10 -> Other 12 | 11 -> Other 13 | 12 -> Other 14 | 13 -> Other 15 | 14 -> Other 16 | 15 -> Other 17 | 16 -> Other 18 | 17 -> Other 19 | 18 -> Other 20 | 19 -> Other 21 | 20 -> Twenty 22 | 21 -> Other 23 | 22 -> Other 24 | 23 -> Other 25 | 24 -> Other 26 | 25 -> Other 27 | -------------------------------------------------------------------------------- /src/test/test25.mini: -------------------------------------------------------------------------------- 1 | fun test1(N) do 2 | for I in 1 .. 10 do 3 | must print('I = {I}\n') 4 | for J in 1 .. 10 do 5 | must print('J = {J}\n') 6 | if (I * I) + (J * J) = (N * N) then 7 | exit exit '{I}^2 + {J}^2 = {N}^2' 8 | end 9 | end 10 | end 11 | end 12 | 13 | print(test1(5), "\n") 14 | 15 | fun test2(F) do 16 | print('Starting\n') 17 | var I := 1 18 | must print('Must: I = {I}\n') 19 | I := 2 20 | I := F() 21 | print('Finishing: I = {I}\n') 22 | I := 3 23 | end 24 | 25 | do 26 | test2(;) 5 27 | test2(;) 1 / 0 28 | on Error do 29 | print('{Error:type}: {Error:message}\n') 30 | end 31 | -------------------------------------------------------------------------------- /src/test/test25.out: -------------------------------------------------------------------------------- 1 | J = 1 2 | J = 2 3 | J = 3 4 | J = 4 5 | J = 5 6 | J = 6 7 | J = 7 8 | J = 8 9 | J = 9 10 | J = 10 11 | I = 1 12 | J = 1 13 | J = 2 14 | J = 3 15 | J = 4 16 | J = 5 17 | J = 6 18 | J = 7 19 | J = 8 20 | J = 9 21 | J = 10 22 | I = 2 23 | J = 1 24 | J = 2 25 | J = 3 26 | J = 4 27 | I = 3 28 | 3^2 + 4^2 = 5^2 29 | Starting 30 | Finishing: I = 5 31 | Must: I = 3 32 | Starting 33 | Must: I = 2 34 | ValueError: Division by 0 35 | -------------------------------------------------------------------------------- /src/test/test26.mini: -------------------------------------------------------------------------------- 1 | fun test1(N) do 2 | main :- for I in 1 .. 10 do 3 | must print('I = {I}\n') 4 | for J in 1 .. 10 do 5 | if I * J = 9 then 6 | main :- next 7 | end 8 | must print('J = {J}\n') 9 | if (I * I) + (J * J) = (N * N) then 10 | main :- exit '{I}^2 + {J}^2 = {N}^2' 11 | end 12 | end 13 | end 14 | end 15 | 16 | print(test1(5), "\n") 17 | 18 | fun test2(F) do 19 | print('Starting\n') 20 | var I := 1 21 | must print('Must: I = {I}\n') 22 | I := 2 23 | I := F() 24 | print('Finishing: I = {I}\n') 25 | I := 3 26 | end 27 | 28 | do 29 | test2(;) 5 30 | test2(;) 1 / 0 31 | on Error do 32 | print('{Error:type}: {Error:message}\n') 33 | end 34 | -------------------------------------------------------------------------------- /src/test/test26.out: -------------------------------------------------------------------------------- 1 | J = 1 2 | J = 2 3 | J = 3 4 | J = 4 5 | J = 5 6 | J = 6 7 | J = 7 8 | J = 8 9 | I = 1 10 | J = 1 11 | J = 2 12 | J = 3 13 | J = 4 14 | J = 5 15 | J = 6 16 | J = 7 17 | J = 8 18 | J = 9 19 | J = 10 20 | I = 2 21 | J = 1 22 | J = 2 23 | I = 3 24 | J = 1 25 | J = 2 26 | J = 3 27 | I = 4 28 | 4^2 + 3^2 = 5^2 29 | Starting 30 | Finishing: I = 5 31 | Must: I = 3 32 | Starting 33 | Must: I = 2 34 | ValueError: Division by 0 35 | -------------------------------------------------------------------------------- /src/test/test27.mini: -------------------------------------------------------------------------------- 1 | enum: colour("Red", "Orange", "Yellow", "Green", "Blue", "Violet") 2 | 3 | print('Colours = {list(colour)}\n') 4 | print('{colour::Yellow} .. {colour::Violet} = {list(colour::Yellow .. colour::Violet)}\n') 5 | print('{colour::Violet} .. {colour::Yellow} = {list(colour::Violet .. colour::Yellow)}\n') 6 | 7 | print('Red + Blue = {integer(colour::Red) + integer(colour::Blue)}\n') 8 | 9 | fun test_colour(Colour) do 10 | switch Colour: colour 11 | case ::Red, ::Orange, ::Violet do 12 | "reddish" 13 | case ::Yellow .. ::Green do 14 | "greenish" 15 | else 16 | "blueish" 17 | end 18 | end 19 | 20 | for Name in ["Red", "Orange", "Yellow", "Green", "Blue", "Violet", "Turquoise"] do 21 | print('{Name} -> ') 22 | let Colour := colour(Name) 23 | print(test_colour(Colour), "\n") 24 | on Error do 25 | print('Error = {Error:message}\n') 26 | end 27 | 28 | enum::cyclic: day("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") 29 | 30 | print('Days = {list(day)}\n') 31 | print('{day::Mon} .. {day::Fri} = {list(day::Mon .. day::Fri)}\n') 32 | print('{day::Fri} .. {day::Mon} = {list(day::Fri .. day::Mon)}\n') 33 | 34 | 35 | fun test_day(Day) do 36 | switch Day: day 37 | case ::Tue, ::Thu do 38 | "work" 39 | case ::Fri .. ::Mon do 40 | "play" 41 | else 42 | "sleep" 43 | end 44 | end 45 | 46 | for Name in ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] do 47 | print('{Name} -> ') 48 | let Day := day(Name) 49 | print(test_day(Day), "\n") 50 | on Error do 51 | print('Error = {Error:message}\n') 52 | end 53 | 54 | -------------------------------------------------------------------------------- /src/test/test27.out: -------------------------------------------------------------------------------- 1 | Colours = [Red, Orange, Yellow, Green, Blue, Violet] 2 | Yellow .. Violet = [Yellow, Green, Blue, Violet] 3 | Violet .. Yellow = [] 4 | Red + Blue = 6 5 | Red -> reddish 6 | Orange -> reddish 7 | Yellow -> greenish 8 | Green -> greenish 9 | Blue -> blueish 10 | Violet -> reddish 11 | Turquoise -> Error = Invalid enum name 12 | Days = [Mon, Tue, Wed, Thu, Fri, Sat, Sun] 13 | Mon .. Fri = [Mon, Tue, Wed, Thu, Fri] 14 | Fri .. Mon = [Fri, Sat, Sun, Mon] 15 | Mon -> play 16 | Tue -> work 17 | Wed -> sleep 18 | Thu -> work 19 | Fri -> play 20 | Sat -> play 21 | Sun -> play 22 | -------------------------------------------------------------------------------- /src/test/test28.mini: -------------------------------------------------------------------------------- 1 | let A := 2147483647 2 | let B := -2147483648 3 | let C := A * 8 4 | let D := B * 8 5 | 6 | let Xs := {"A" is A, "B" is B, "C" is C, "D" is D} 7 | 8 | for Xn, X in Xs do 9 | print('{Xn} = {X}\n') 10 | print('{X} + 1 = {X + 1}\n') 11 | print('{X} - 1 = {X - 1}\n') 12 | print('1 + {X} = {1 + X}\n') 13 | print('1 - {X} = {1 - X}\n') 14 | print('{X} * 2 = {X * 2}\n') 15 | print('2 * {X} = {2 * X}\n') 16 | print('{X} / 2 = {X / 2}\n') 17 | print('{X} * 4096 = {X * 4096}\n') 18 | print('4096 * {X} = {4096 * X}\n') 19 | print('{X} / 4096 = {X / 4096}\n') 20 | print("---\n") 21 | end 22 | 23 | for Xn, X in Xs do 24 | for Yn, Y in Xs do 25 | print('{X} + {Y} = {X + Y}\n') 26 | print('{X} - {Y} = {X - Y}\n') 27 | print("---\n") 28 | end 29 | end -------------------------------------------------------------------------------- /src/test/test28.out: -------------------------------------------------------------------------------- 1 | A = 2147483647 2 | 2147483647 + 1 = 2147483648 3 | 2147483647 - 1 = 2147483646 4 | 1 + 2147483647 = 2147483648 5 | 1 - 2147483647 = -2147483646 6 | 2147483647 * 2 = 4294967294 7 | 2 * 2147483647 = 4294967294 8 | 2147483647 / 2 = 1073741823.5 9 | 2147483647 * 4096 = 8796093018112 10 | 4096 * 2147483647 = 8796093018112 11 | 2147483647 / 4096 = 524287.999755859 12 | --- 13 | B = -2147483648 14 | -2147483648 + 1 = -2147483647 15 | -2147483648 - 1 = -2147483649 16 | 1 + -2147483648 = -2147483647 17 | 1 - -2147483648 = 2147483649 18 | -2147483648 * 2 = -4294967296 19 | 2 * -2147483648 = -4294967296 20 | -2147483648 / 2 = -1073741824 21 | -2147483648 * 4096 = -8796093022208 22 | 4096 * -2147483648 = -8796093022208 23 | -2147483648 / 4096 = -524288 24 | --- 25 | C = 17179869176 26 | 17179869176 + 1 = 17179869177 27 | 17179869176 - 1 = 17179869175 28 | 1 + 17179869176 = 17179869177 29 | 1 - 17179869176 = -17179869175 30 | 17179869176 * 2 = 34359738352 31 | 2 * 17179869176 = 34359738352 32 | 17179869176 / 2 = 8589934588 33 | 17179869176 * 4096 = 70368744144896 34 | 4096 * 17179869176 = 70368744144896 35 | 17179869176 / 4096 = 4194303.99804688 36 | --- 37 | D = -17179869184 38 | -17179869184 + 1 = -17179869183 39 | -17179869184 - 1 = -17179869185 40 | 1 + -17179869184 = -17179869183 41 | 1 - -17179869184 = 17179869185 42 | -17179869184 * 2 = -34359738368 43 | 2 * -17179869184 = -34359738368 44 | -17179869184 / 2 = -8589934592 45 | -17179869184 * 4096 = -70368744177664 46 | 4096 * -17179869184 = -70368744177664 47 | -17179869184 / 4096 = -4194304 48 | --- 49 | 2147483647 + 2147483647 = 4294967294 50 | 2147483647 - 2147483647 = 0 51 | --- 52 | 2147483647 + -2147483648 = -1 53 | 2147483647 - -2147483648 = 4294967295 54 | --- 55 | 2147483647 + 17179869176 = 19327352823 56 | 2147483647 - 17179869176 = -15032385529 57 | --- 58 | 2147483647 + -17179869184 = -15032385537 59 | 2147483647 - -17179869184 = 19327352831 60 | --- 61 | -2147483648 + 2147483647 = -1 62 | -2147483648 - 2147483647 = -4294967295 63 | --- 64 | -2147483648 + -2147483648 = -4294967296 65 | -2147483648 - -2147483648 = 0 66 | --- 67 | -2147483648 + 17179869176 = 15032385528 68 | -2147483648 - 17179869176 = -19327352824 69 | --- 70 | -2147483648 + -17179869184 = -19327352832 71 | -2147483648 - -17179869184 = 15032385536 72 | --- 73 | 17179869176 + 2147483647 = 19327352823 74 | 17179869176 - 2147483647 = 15032385529 75 | --- 76 | 17179869176 + -2147483648 = 15032385528 77 | 17179869176 - -2147483648 = 19327352824 78 | --- 79 | 17179869176 + 17179869176 = 34359738352 80 | 17179869176 - 17179869176 = 0 81 | --- 82 | 17179869176 + -17179869184 = -8 83 | 17179869176 - -17179869184 = 34359738360 84 | --- 85 | -17179869184 + 2147483647 = -15032385537 86 | -17179869184 - 2147483647 = -19327352831 87 | --- 88 | -17179869184 + -2147483648 = -19327352832 89 | -17179869184 - -2147483648 = -15032385536 90 | --- 91 | -17179869184 + 17179869176 = -8 92 | -17179869184 - 17179869176 = -34359738360 93 | --- 94 | -17179869184 + -17179869184 = -34359738368 95 | -17179869184 - -17179869184 = 0 96 | --- 97 | -------------------------------------------------------------------------------- /src/test/test3.mini: -------------------------------------------------------------------------------- 1 | var L := [1, 2, "hello", 4, 5] 2 | 3 | do 4 | for X in L do 5 | print('{X} * 2 = {X * 2}\n') 6 | if X = 4 then 7 | exit "a" * 2 8 | end 9 | on Error do 10 | print('Correct! An error has occurred 1: {Error:type}\n') 11 | end 12 | on Error do 13 | print('Correct! An error has occurred 2: {Error:type}\n') 14 | end 15 | 16 | print('Before X loop\n') 17 | for X in 1 .. 5 do 18 | print('Before Y loop\n') 19 | for Y in 11 .. 15 do 20 | print('X = {X}, Y = {Y}\n') 21 | if X = 3 and Y = 13 then 22 | exit next 23 | end 24 | end 25 | print('After Y loop\n') 26 | end 27 | 28 | for Z in 1 .. 10 do 29 | print('Z = {Z}\n') 30 | if Z = 5 then 31 | print('5!\n') 32 | 'a' * 2 33 | on Error do 34 | print('Correct! An error has occurred 3: {Error:type}\n') 35 | next 36 | elseif Z = 9 then 37 | 'a' * 2 38 | end 39 | print('... and on\n') 40 | on Error do 41 | print('Correct! An error has occurred 4: {Error:type}\n') 42 | end -------------------------------------------------------------------------------- /src/test/test3.out: -------------------------------------------------------------------------------- 1 | 1 * 2 = 2 2 | 2 * 2 = 4 3 | Correct! An error has occurred 1: MethodError 4 | 4 * 2 = 8 5 | Correct! An error has occurred 2: MethodError 6 | Before X loop 7 | Before Y loop 8 | X = 1, Y = 11 9 | X = 1, Y = 12 10 | X = 1, Y = 13 11 | X = 1, Y = 14 12 | X = 1, Y = 15 13 | After Y loop 14 | Before Y loop 15 | X = 2, Y = 11 16 | X = 2, Y = 12 17 | X = 2, Y = 13 18 | X = 2, Y = 14 19 | X = 2, Y = 15 20 | After Y loop 21 | Before Y loop 22 | X = 3, Y = 11 23 | X = 3, Y = 12 24 | X = 3, Y = 13 25 | Before Y loop 26 | X = 4, Y = 11 27 | X = 4, Y = 12 28 | X = 4, Y = 13 29 | X = 4, Y = 14 30 | X = 4, Y = 15 31 | After Y loop 32 | Before Y loop 33 | X = 5, Y = 11 34 | X = 5, Y = 12 35 | X = 5, Y = 13 36 | X = 5, Y = 14 37 | X = 5, Y = 15 38 | After Y loop 39 | Z = 1 40 | ... and on 41 | Z = 2 42 | ... and on 43 | Z = 3 44 | ... and on 45 | Z = 4 46 | ... and on 47 | Z = 5 48 | 5! 49 | Correct! An error has occurred 3: MethodError 50 | Z = 6 51 | ... and on 52 | Z = 7 53 | ... and on 54 | Z = 8 55 | ... and on 56 | Z = 9 57 | Correct! An error has occurred 4: MethodError 58 | Z = 10 59 | ... and on 60 | -------------------------------------------------------------------------------- /src/test/test4.mini: -------------------------------------------------------------------------------- 1 | var L := [1, 2, "hello", 4, 5] 2 | 3 | for Key, Value in L do 4 | print('Key = {Key}, Value = {Value}\n') 5 | end 6 | 7 | var M := {"a" is 100, 10 is "b"} 8 | 9 | for Key, Value in M do 10 | print('Key = {Key}, Value = {Value}\n') 11 | end 12 | 13 | fun test(X) do 14 | let (A, B, C) := X 15 | print('A = {A}, B = {B}, C = {C}\n') 16 | end 17 | 18 | test((1, 2, 3)) 19 | test([1, 2, 3]) -------------------------------------------------------------------------------- /src/test/test4.out: -------------------------------------------------------------------------------- 1 | Key = 1, Value = 1 2 | Key = 2, Value = 2 3 | Key = 3, Value = hello 4 | Key = 4, Value = 4 5 | Key = 5, Value = 5 6 | Key = a, Value = 100 7 | Key = 10, Value = b 8 | A = 1, B = 2, C = 3 9 | A = 1, B = 2, C = 3 10 | -------------------------------------------------------------------------------- /src/test/test5.mini: -------------------------------------------------------------------------------- 1 | var L := ["a", "b", "c", "d", "e"] 2 | 3 | for N, X in L do 4 | print('N = {N}, X = {X}\n') 5 | end 6 | 7 | var F := [] 8 | 9 | for X in L do 10 | F:put(fun() print('X = {X}\n')) 11 | X := 'x{X}' 12 | end 13 | 14 | for F1 in F do F1() end 15 | 16 | print('L = {L}\n') 17 | 18 | var M := ["a", "b", "c", "d", "e"] 19 | 20 | var G := [] 21 | 22 | for N, Y in M do 23 | G:put(fun() print('Y[{N}] = {Y}\n')) 24 | Y := 'y{Y}' 25 | end 26 | 27 | for G1 in G do G1() end 28 | 29 | print('M = {M}\n') -------------------------------------------------------------------------------- /src/test/test5.out: -------------------------------------------------------------------------------- 1 | N = 1, X = a 2 | N = 2, X = b 3 | N = 3, X = c 4 | N = 4, X = d 5 | N = 5, X = e 6 | X = xa 7 | X = xb 8 | X = xc 9 | X = xd 10 | X = xe 11 | L = [xa, xb, xc, xd, xe] 12 | Y[1] = ya 13 | Y[2] = yb 14 | Y[3] = yc 15 | Y[4] = yd 16 | Y[5] = ye 17 | M = [ya, yb, yc, yd, ye] 18 | -------------------------------------------------------------------------------- /src/test/test6.mini: -------------------------------------------------------------------------------- 1 | var X := 1 2 | var Y := nil 3 | 4 | if X then 5 | print('Correct\n') 6 | else 7 | print('Wrong\n') 8 | end 9 | 10 | if Y then 11 | print('Wrong\n') 12 | else 13 | print('Correct\n') 14 | end 15 | 16 | var S := "Hello world!" 17 | 18 | if var Z := S:find("llo") then 19 | print('Z = {Z}\n') 20 | else 21 | print('Wrong\n') 22 | end 23 | 24 | if var Z := S:find("elo") then 25 | print('Wrong\n') 26 | elseif var W := S:find("wor") then 27 | print('W = {W}\n') 28 | else 29 | print('Wrong\n') 30 | end 31 | 32 | -------------------------------------------------------------------------------- /src/test/test6.out: -------------------------------------------------------------------------------- 1 | Correct 2 | Correct 3 | Z = 3 4 | W = 7 5 | -------------------------------------------------------------------------------- /src/test/test7.mini: -------------------------------------------------------------------------------- 1 | var F1 := fun(A, B, C) do 2 | print('A = {A}, B = {B}, C = {C}\n') 3 | end 4 | 5 | F1(1, 2, 3) 6 | 7 | var F2 := F1 $! [10] 8 | 9 | F2(1, 2, 3) 10 | 11 | var F3 := F2 $! [20] 12 | 13 | F3(1, 2, 3) 14 | 15 | var G1 := print $! [10] 16 | 17 | G1(1, 2, 3) -------------------------------------------------------------------------------- /src/test/test7.out: -------------------------------------------------------------------------------- 1 | A = 1, B = 2, C = 3 2 | A = 10, B = 1, C = 2 3 | A = 10, B = 20, C = 1 4 | 10123 -------------------------------------------------------------------------------- /src/test/test8.mini: -------------------------------------------------------------------------------- 1 | var test := fun(Start, Stop, Step) do 2 | var Value := Start 3 | loop while Value <= Stop 4 | susp Value 5 | Value := old + Step 6 | end 7 | ret nil 8 | end 9 | 10 | for X in test $! [1, 10, 3] do 11 | print('X = {X}\n') 12 | end 13 | 14 | print(list(test $! [1, 100, 7]), "\n") -------------------------------------------------------------------------------- /src/test/test8.out: -------------------------------------------------------------------------------- 1 | X = 1 2 | X = 4 3 | X = 7 4 | X = 10 5 | [1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99] 6 | -------------------------------------------------------------------------------- /src/test/test9.mini: -------------------------------------------------------------------------------- 1 | let test := fun(A, B) do 2 | var C := 1 3 | let D := 2 4 | print('C = {C}\n') 5 | print('D = {D}\n') 6 | print('C + D = {C + D}\n') 7 | test2() 8 | end 9 | 10 | var test2 := fun() do 11 | print("In test2!\n") 12 | end 13 | 14 | test(10, 20) -------------------------------------------------------------------------------- /src/test/test9.out: -------------------------------------------------------------------------------- 1 | C = 1 2 | D = 2 3 | C + D = 3 4 | In test2! 5 | -------------------------------------------------------------------------------- /src/test/test_gir1.mini: -------------------------------------------------------------------------------- 1 | def Gtk := gir("Gtk") 2 | 3 | var W := Gtk("Window"):new(Gtk("WindowType")("toplevel")) 4 | 5 | var B := Gtk("Button"):new_with_label("Click me!") 6 | 7 | W:add(B) 8 | 9 | B:connect("clicked";) print("Button clicked!\n") 10 | 11 | W:show_all 12 | 13 | W:connect("destroy";) Gtk("main_quit")() 14 | 15 | Gtk("main")() -------------------------------------------------------------------------------- /src/test/test_gir2.mini: -------------------------------------------------------------------------------- 1 | def Gtk := gir("Gtk"), Gdk := gir("Gdk") 2 | 3 | var W := Gtk("Window"):new(Gtk("WindowType")("toplevel")) 4 | 5 | var TV := Gtk("TextView"):new 6 | var TB := TV:get_buffer 7 | 8 | var TI := Gtk("TextIter"):new 9 | 10 | TB:get_start_iter(TI) 11 | for I in 1 .. 10 do 12 | TB:insert(TI, "Hello world\n", -1) 13 | end 14 | 15 | W:add(TV) 16 | 17 | W:show_all 18 | 19 | var R := Gdk("Rectangle"):new 20 | 21 | TV:get_visible_rect(R) 22 | 23 | print('R = {R:x}, {R:y}, {R:width}, {R:height}\n') 24 | R:x := 10 25 | R:width := 1289 26 | print('R = {R:x}, {R:y}, {R:width}, {R:height}\n') 27 | 28 | W:connect("destroy";) do 29 | TV:get_visible_rect(R) 30 | print('R = {R:x}, {R:y}, {R:width}, {R:height}\n') 31 | Gtk("main_quit")() 32 | end 33 | 34 | Gtk("main")() -------------------------------------------------------------------------------- /src/timelib_mem.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMELIB_MEM_H 2 | #define TIMELIB_MEM_H 3 | 4 | #include 5 | #include 6 | 7 | #define timelib_malloc GC_malloc 8 | #define timelib_realloc GC_realloc 9 | #define timelib_free nop_free 10 | #define timelib_calloc GC_calloc 11 | #define timelib_strdup GC_strdup 12 | 13 | static inline void nop_free(void *Ptr) {} 14 | static inline void *GC_calloc(size_t N, size_t M) { 15 | return GC_malloc(N * M); 16 | } 17 | 18 | static inline char *timelib_strndup(const char *S, size_t N) { 19 | char *C; 20 | size_t M; 21 | M = strlen(S); 22 | if (N > M) N = M; 23 | C = GC_malloc_atomic(N + 1); 24 | C[N] = 0; 25 | return memcpy(C, S, N); 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/tre.patch: -------------------------------------------------------------------------------- 1 | --- lib/tre-compile.c 2023-03-15 10:52:09.903301590 +0000 2 | +++ lib/tre-compile.c.new 2023-03-15 10:53:00.390079564 +0000 3 | @@ -715,6 +715,7 @@ 4 | *result = tre_ast_new_literal(mem, min, max, pos); 5 | if (*result == NULL) 6 | status = REG_ESPACE; 7 | + ((tre_literal_t*)(*result)->obj)->u.class = lit->u.class; 8 | 9 | if (pos > *max_pos) 10 | *max_pos = pos; 11 | -------------------------------------------------------------------------------- /src/weakmap.h: -------------------------------------------------------------------------------- 1 | #ifndef WEAKMAP_H 2 | #define WEAKMAP_H 3 | 4 | #include "ml_config.h" 5 | #include 6 | 7 | #ifdef ML_THREADSAFE 8 | 9 | #include 10 | 11 | #endif 12 | 13 | typedef struct weakmap_node_t weakmap_node_t; 14 | 15 | typedef struct { 16 | weakmap_node_t *Nodes; 17 | #ifdef ML_THREADSAFE 18 | pthread_mutex_t Lock[1]; 19 | #endif 20 | size_t Mask, Space; //, Deleted; 21 | } weakmap_t; 22 | 23 | #ifdef ML_THREADSAFE 24 | 25 | #define WEAKMAP_INIT (weakmap_t){NULL, {PTHREAD_MUTEX_INITIALIZER}, 0, 0} 26 | 27 | #else 28 | 29 | #define WEAKMAP_INIT (weakmap_t){NULL, 0, 0} 30 | 31 | #endif 32 | 33 | void *weakmap_insert(weakmap_t *Map, const char *Key, int Length, void *(*missing)(const char *, int)); 34 | 35 | int weakmap_foreach(weakmap_t *Map, void *Data, int (*callback)(const char *, void *, void *)); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/whereami.h: -------------------------------------------------------------------------------- 1 | // (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses 2 | // without any warranty. 3 | // by Gregory Pakosz (@gpakosz) 4 | // https://github.com/gpakosz/whereami 5 | 6 | #ifndef WHEREAMI_H 7 | #define WHEREAMI_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #ifndef WAI_FUNCSPEC 14 | #define WAI_FUNCSPEC 15 | #endif 16 | #ifndef WAI_PREFIX 17 | #define WAI_PREFIX(function) wai_##function 18 | #endif 19 | 20 | /** 21 | * Returns the path to the current executable. 22 | * 23 | * Usage: 24 | * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to 25 | * retrieve the length of the path 26 | * - allocate the destination buffer with `path = (char*)malloc(length + 1);` 27 | * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the 28 | * path 29 | * - add a terminal NUL character with `path[length] = '\0';` 30 | * 31 | * @param out destination buffer, optional 32 | * @param capacity destination buffer capacity 33 | * @param dirname_length optional recipient for the length of the dirname part 34 | * of the path. 35 | * 36 | * @return the length of the executable path on success (without a terminal NUL 37 | * character), otherwise `-1` 38 | */ 39 | WAI_FUNCSPEC 40 | int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); 41 | 42 | /** 43 | * Returns the path to the current module 44 | * 45 | * Usage: 46 | * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve 47 | * the length of the path 48 | * - allocate the destination buffer with `path = (char*)malloc(length + 1);` 49 | * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path 50 | * - add a terminal NUL character with `path[length] = '\0';` 51 | * 52 | * @param out destination buffer, optional 53 | * @param capacity destination buffer capacity 54 | * @param dirname_length optional recipient for the length of the dirname part 55 | * of the path. 56 | * 57 | * @return the length of the module path on success (without a terminal NUL 58 | * character), otherwise `-1` 59 | */ 60 | WAI_FUNCSPEC 61 | int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif // #ifndef WHEREAMI_H 68 | --------------------------------------------------------------------------------