├── .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 |
--------------------------------------------------------------------------------