~maelkum/viuavm

fe355eb183233d7ff7da8a682941b57f3e8267cb — Marek Marecki 7 days ago 38432de + c3c2c58 master
Merge branch 'devel'
302 files changed, 4181 insertions(+), 2243 deletions(-)

M .clang-format
A .issue/objects/issues/05/057fe30484fb6bfcc2407b1924803b854d96922f5f759e2046e1ea12fc557438023bdccd9dd30b47de8b87cd04c76b0f/diff/6547d4766bb1281a95fb55fe4519b5949d7e64b2669aa511836ad1a850dd478275adbba25a5cb5bd3f0a753a1fdcc0a0.json
D .issue/objects/issues/1a/1a7c4657ba9991d6a17349a55d5310033d02fe19/diff/fceb270e9d962c217ec23cf0ad0577be7c87f9a7.json
D .issue/objects/issues/30/30cf2fb8dd9b184190bbc19c627fa5e351cea5ae/diff/4231488e3ad2d81770af618c25605bc9aa66fdf5.json
D .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/6508044eecb9455bc53fb1a09a0aa619f42496f1f091aadb76f6e45e76c07064363cbd364e69249f22f5e0584c7399a1.json
D .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/7c9a092b208585e63d313a4c236af62e7a86ae6c167ddfed862e3c375c159e8a14fd5e71e5dc69cf50093e14c27edd76.json
D .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/a56dd789d799946db6e2dc77a9aaa0807d89668c63777333138fb5ca26a37f48469121d4d3a9f3cb8311664c6ede7215.json
D .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/1074de16304666e5b4536e688d0fff9b2a57482c53cd7c809d8aad6261c7f27e1762cc502a0681ed5c300c7e2fdb34a3.json
D .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/739e28a00a53c63548f80db8d9743455799534dc1caf8a9e1b7b3cadda54bd5838d3771728d66be96a3b3ff3a99a58c6.json
D .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/8473d2abca3c84f6af2204920544b03722c2f44cfa14711ed2dd38f1c751a1e0b3a55da45013cb56c0d855591a493148.json
D .issue/objects/issues/4f/4fecd9277051fd84bd63329b43083550bf73d67b/diff/7ed97c23de5adc94cbeb126df2af833ff7559e5b.json
D .issue/objects/issues/50/505732b9905aae8656f94b9f45847fa91ce55c7b/diff/3c73126ab375f439a2524b09ed875680a3099fb7.json
D .issue/objects/issues/60/607b9619609c0f442a1f222c6b36c0e3f84a325e/diff/d753bf4760638bf07e24b14fad0d02e41ee2aa5d.json
A .issue/objects/issues/62/6223d3b5cec5343dc8444eb2f95b08ebb7621a5f2d4f919cac6f577e8836eacb81eddf17238efccae132811ce5781204/diff/158db5c6ad7fd174f649f44860aa9e34cbe3cae55420bcba101ecb1fd21a13d7906829d27f13bf7235e18b4b469fade9.json
A .issue/objects/issues/62/6223d3b5cec5343dc8444eb2f95b08ebb7621a5f2d4f919cac6f577e8836eacb81eddf17238efccae132811ce5781204/diff/983456ab672f0dfc8454f3b4527c193c4cafa63d35d5c6b3e87baeac2af41bdef82e1295d21465ad0d97143533cb3e59.json
D .issue/objects/issues/65/65debffc0067bf56000dd29de193435df27f27a5f0414493a14af77be002f5a036f41560e160ccd5ebad3fe0563fe688/diff/49b1aafa0b570363977db6cf622a8541040ffa7fa7a20d9ed277d8f34b34074d4aa5d22540bc9222c331937041f167f3.json
D .issue/objects/issues/65/65debffc0067bf56000dd29de193435df27f27a5f0414493a14af77be002f5a036f41560e160ccd5ebad3fe0563fe688/diff/7162b9b34cc0f91d9d4fbd840c339024c336d5f10a16ce2304d7d0b02338c397a2b5bcfc1850f9b5509229d802bbe98f.json
A .issue/objects/issues/6f/6fd00ea0caf449f20da20383460bce952ea99529b88fe80a51490927934df2a0ac3e367880a05bb6994f023b4be9bd5c/diff/76af2459658effe182eff026c6269ab7d49d35557290fa887ffc7b5e90f2003740c4122ad87e0e6766da54e0ac8f7178.json
A .issue/objects/issues/79/7935629c4422450d6e6eefaad96cb28a97a580ae8b71e268bcaf384a5eb3536bcc49ecd2dea36d862c2d6653a0701d66/diff/77af79f68bc221659d526b7311531ea386179b83ec7b67c501f7d2e799761ed246b4292f792430d95066717ce4993ffb.json
D .issue/objects/issues/85/85aae918a0330e72f342289888a8242b23ef42e1/diff/a4db927ef493c87d2ed4ef9999981093348bca0a.json
A .issue/objects/issues/a6/a6e2c20a78cf246810742d4aa8f68538b22117e35db438d705239ad375898d4c243648ea2ea1889e1369a663660331f6/diff/6c335e6f34dc6e466ef746773c9e3657a352417e391d0125c8ea5eb4544f3d643b76a51588b33f2f193ce78131cc852d.json
A .issue/objects/issues/a6/a6e2c20a78cf246810742d4aa8f68538b22117e35db438d705239ad375898d4c243648ea2ea1889e1369a663660331f6/diff/7e2c09abfcca56c6e5be1742622482cccb660c75096350867962e8bd5919a182a7d5c731b26561b1d034f4ec81036e6a.json
D .issue/objects/issues/a8/a80c9ec1d1cf8882665871624c020649766bc094/diff/192a3bcfc97184e215cd64896000a4ee702de2c8.json
A .issue/objects/issues/aa/aa38113d2188560e87ea097ef005cc9d06fb53421fe08ee1df839dd0c7338668a7d28d4992800e5e3c20235b8a3f47b6/diff/75e1f609f490746809d34efc2a9b5b05e0b7c19b49b812e9d5c45d6a81c5894f5d6cafbe6c78b4a69c8900e36fcd6248.json
D .issue/objects/issues/c4/c4c8625c12bf57c760834eae81dff09daa236528/diff/eaaf7b1199fc957305a4e1da3222f3571c0d7c0b.json
D .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/comments/660c503ee2c7ac985a9bba8b5525ffc9644e68a0.json
D .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/comments/e441d063260914c074b1fa157e0d07b55eefa72b.json
D .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/diff/a0ca9471d9c87e4758c99bd86a7829cd8f58f33c.json
A .issue/objects/issues/fe/fec884e6c5cb3acbd57905050fa9564d340319558e59d14094b9bc71c47a278427002c0b364b7c32520341689bef5c83/diff/7dcc3af2c8d0336c4e3fbc47d279c07bd52a12a0b27c93d79fbaf98458d56f646df9e952dc5ec025da012d3373ae973c.json
M Changelog.markdown
M Makefile
M include/viua/assembler/backend/op_assemblers.h
M include/viua/assembler/frontend/parser.h
M include/viua/assembler/frontend/static_analyser.h
M include/viua/assembler/util/pretty_printer.h
M include/viua/assert.h
M include/viua/bytecode/bytetypedef.h
M include/viua/bytecode/codec.h
M include/viua/bytecode/codec/main.h
M include/viua/bytecode/maps.h
M include/viua/bytecode/opcodes.h
M include/viua/bytecode/operand_types.h
M include/viua/cg/assembler/assembler.h
M include/viua/cg/tools.h
M include/viua/exceptions.h
M include/viua/front/asm.h
M include/viua/front/vm.h
M include/viua/include/module.h
M include/viua/kernel/catcher.h
M include/viua/kernel/frame.h
M include/viua/kernel/kernel.h
M include/viua/kernel/registerset.h
M include/viua/kernel/tryframe.h
M include/viua/loader.h
M include/viua/pid.h
M include/viua/printutils.h
M include/viua/process.h
M include/viua/program.h
M include/viua/scheduler/ffi.h
M include/viua/scheduler/io.h
M include/viua/scheduler/io/interactions.h
M include/viua/scheduler/process.h
M include/viua/support/env.h
M include/viua/tooling/errors/compile_time/errors.h
M include/viua/tooling/libs/lexer/normaliser.h
M include/viua/tooling/libs/parser/parser.h
M include/viua/tooling/libs/static_analyser/static_analyser.h
M include/viua/types/atom.h
M include/viua/types/bits.h
M include/viua/types/boolean.h
M include/viua/types/closure.h
M include/viua/types/exception.h
M include/viua/types/float.h
M include/viua/types/function.h
M include/viua/types/integer.h
M include/viua/types/io.h
M include/viua/types/number.h
D include/viua/types/object.h
M include/viua/types/pointer.h
M include/viua/types/process.h
M include/viua/types/reference.h
M include/viua/types/string.h
M include/viua/types/struct.h
M include/viua/types/text.h
M include/viua/types/value.h
M include/viua/types/vector.h
M include/viua/util/exceptions.h
M include/viua/util/memory.h
M include/viua/util/range.h
M include/viua/util/string/ops.h
M include/viua/util/vector_view.h
M include/viua/version.h
M sample/asm/external/throwing.asm
M sample/asm/watchdog/already_spawned.asm
M sample/asm/watchdog/death_message.asm
M sample/asm/watchdog/restarting_process.asm
M sample/types/Pointer/check_if_is_expired.asm
M scripts/compile
A scripts/get_code_fingerprint.sh
M scripts/test_full.sh
M scripts/watch.sh
M src/assembler/backend/op_assemblers/assemble_op_frame.cpp
M src/assembler/backend/op_assemblers/assemble_op_if.cpp
M src/assembler/backend/op_assemblers/assemble_op_io_wait.cpp
M src/assembler/backend/op_assemblers/assemble_op_jump.cpp
M src/assembler/frontend/gather.cpp
M src/assembler/frontend/parser.cpp
M src/assembler/frontend/static_analyser/Closure.cpp
M src/assembler/frontend/static_analyser/Register.cpp
M src/assembler/frontend/static_analyser/Register_usage_profile.cpp
M src/assembler/frontend/static_analyser/checkers/check_closure_instantiations.cpp
M src/assembler/frontend/static_analyser/checkers/check_for_unused_registers.cpp
M src/assembler/frontend/static_analyser/checkers/check_for_unused_values.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_allocate_registers.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_arithmetic.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_atom.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_atomeq.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_binary_logic.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bit_arithmetic.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bit_increment.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bit_rotates.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bit_shifts.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bitat.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bitnot.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bits.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bits_of_integer.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_bitset.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_boolean_and_or.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_call.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_capture.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_capturecopy.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_capturemove.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_closure.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_compare.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_copy.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_defer.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_delete.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_draw.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_enter.cpp
A src/assembler/frontend/static_analyser/checkers/check_op_exception.cpp
A src/assembler/frontend/static_analyser/checkers/check_op_exception_tag.cpp
A src/assembler/frontend/static_analyser/checkers/check_op_exception_value.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_float.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_frame.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_ftoi.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_function.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_if.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_iinc.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_integer.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_integer_of_bits.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_io_cancel.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_io_close.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_io_read.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_io_wait.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_io_write.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_isnull.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_itof.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_izero.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_join.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_jump.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_move.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_not.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_pideq.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_print.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_process.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_ptr.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_ptrlive.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_receive.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_self.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_send.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_stof.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_stoi.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_streq.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_string.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_struct.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_structat.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_structinsert.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_structkeys.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_structremove.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_swap.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_tailcall.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_text.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_textat.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_textcommonprefix.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_textcommonsuffix.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_textconcat.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_texteq.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_textlength.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_textsub.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_throw.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_vat.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_vector.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_vinsert.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_vlen.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_vpop.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_vpush.cpp
M src/assembler/frontend/static_analyser/checkers/check_op_watchdog.cpp
M src/assembler/frontend/static_analyser/checkers/utils.cpp
M src/assembler/frontend/static_analyser/register_usage.cpp
M src/assembler/frontend/static_analyser/verifier.cpp
M src/assembler/util/pretty_printer.cpp
M src/assert.cpp
M src/bytecode/codec/main/decoder.cpp
M src/bytecode/codec/main/encoder.cpp
M src/bytecode/opcd.cpp
M src/cg/assembler/codeextract.cpp
M src/cg/assembler/operands.cpp
M src/cg/assembler/static_analysis.cpp
M src/cg/assembler/utils.cpp
M src/cg/assembler/verify.cpp
M src/cg/disassembler/disassembler.cpp
M src/cg/lex.cpp
M src/cg/lex/cook.cpp
M src/cg/lex/reduce_fns.cpp
M src/cg/tokenizer/tokenize.cpp
M src/cg/tools.cpp
M src/front/asm.cpp
M src/front/asm/assemble_instruction.cpp
M src/front/asm/decode.cpp
M src/front/asm/generate.cpp
M src/front/dis.cpp
M src/front/kernel.cpp
M src/front/lexer.cpp
M src/front/parser.cpp
M src/front/vm.cpp
M src/kernel/frame.cpp
M src/kernel/kernel.cpp
M src/kernel/registerset.cpp
M src/loader.cpp
M src/pid.cpp
M src/printutils.cpp
M src/process.cpp
M src/process/dispatch.cpp
M src/process/instr/arithmetic.cpp
M src/process/instr/bits.cpp
M src/process/instr/bool.cpp
M src/process/instr/calls.cpp
M src/process/instr/cast.cpp
M src/process/instr/closure.cpp
M src/process/instr/concurrency.cpp
M src/process/instr/float.cpp
M src/process/instr/general.cpp
M src/process/instr/int.cpp
M src/process/instr/io.cpp
M src/process/instr/linking.cpp
M src/process/instr/registers.cpp
M src/process/instr/str.cpp
M src/process/instr/struct.cpp
M src/process/instr/tcmechanism.cpp
M src/process/instr/text.cpp
M src/process/instr/vector.cpp
M src/process/stack.cpp
M src/program.cpp
M src/programinstructions.cpp
M src/runtime/imports.cpp
M src/scheduler/ffi/request.cpp
M src/scheduler/ffi/scheduler.cpp
M src/scheduler/io/scheduler.cpp
M src/scheduler/process.cpp
M src/stdlib/io.cpp
M src/stdlib/kitchensink.cpp
M src/stdlib/os.cpp
M src/stdlib/posix/io.cpp
M src/stdlib/posix/network.cpp
M src/stdlib/random.cpp
M src/stdlib/typesystem.cpp
M src/support/env.cpp
M src/support/string.cpp
M src/tooling/errors/compile_time.cpp
M src/tooling/errors/compile_time/Error.cpp
M src/tooling/errors/compile_time/Error_wrapper.cpp
M src/tooling/exec/assembler/main.cpp
M src/tooling/libs/lexer/classifier.cpp
M src/tooling/libs/lexer/normaliser.cpp
M src/tooling/libs/lexer/tokenise.cpp
M src/tooling/libs/parser/parse.cpp
M src/tooling/libs/static_analyser/function_state.cpp
M src/tooling/libs/static_analyser/static_analyser.cpp
M src/tooling/libs/static_analyser/values.cpp
M src/types/atom.cpp
M src/types/bits.cpp
M src/types/boolean.cpp
M src/types/closure.cpp
M src/types/exception.cpp
M src/types/float.cpp
M src/types/function.cpp
M src/types/integer.cpp
M src/types/io.cpp
M src/types/number.cpp
D src/types/object.cpp
M src/types/pointer.cpp
M src/types/process.cpp
M src/types/reference.cpp
M src/types/string.cpp
M src/types/struct.cpp
M src/types/text.cpp
M src/types/value.cpp
M src/types/vector.cpp
M src/util/filesystem.cpp
M src/util/string/escape_sequences.cpp
M src/util/string/ops.cpp
M tests/tests.py
M .clang-format => .clang-format +21 -19
@@ 6,12 6,12 @@ AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands:   true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: true
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None


@@ 40,39 40,41 @@ BreakBeforeInheritanceComma: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakStringLiterals: true
ColumnLimit:     80
CommentPragmas:  '^ IWYU pragma:'
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat:   false
DisableFormat: false
FixNamespaceComments: true
IncludeBlocks: Regroup
SortIncludes: true
IncludeCategories: 
  - Regex:           '^(<|"(viua)/)'
    Priority:        2
  - Regex:           '.*'
    Priority:        1
  - Regex:    '^<(viua)/'
    Priority: 3
  - Regex:    '^<([a-z][a-z_]+)>'
    Priority: 2
  - Regex:    '.*'
    Priority: 1
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth:     4
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakAssignment: 5
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 30
PenaltyBreakFirstLessLess: 10
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 600
PenaltyReturnTypeOnItsOwnLine: 500
PointerAlignment: Left
ReflowComments:  true
SortIncludes:    true
ReflowComments: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false


@@ 83,13 85,13 @@ SpaceBeforeParens: ControlStatements
# SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles:  false
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard:        Cpp11
TabWidth:        4
UseTab:          Never
Standard: Cpp11
TabWidth: 4
UseTab: Never
...


A .issue/objects/issues/05/057fe30484fb6bfcc2407b1924803b854d96922f5f759e2046e1ea12fc557438023bdccd9dd30b47de8b87cd04c76b0f/diff/6547d4766bb1281a95fb55fe4519b5949d7e64b2669aa511836ad1a850dd478275adbba25a5cb5bd3f0a753a1fdcc0a0.json => .issue/objects/issues/05/057fe30484fb6bfcc2407b1924803b854d96922f5f759e2046e1ea12fc557438023bdccd9dd30b47de8b87cd04c76b0f/diff/6547d4766bb1281a95fb55fe4519b5949d7e64b2669aa511836ad1a850dd478275adbba25a5cb5bd3f0a753a1fdcc0a0.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.658353}, {"action": "set-message", "params": {"text": "Static analyser breaks on relative jumps\n\nThe mnemonic_counter used to map instructions to lines gets messed up\nand the static analyser loses track of where it is. This bug surfaces\nif there are non-mnemonic lines in an instruction block (e.g. \".mark:\"\ndirectives).\n\nThe signature of this bug is that the error report contains several\nbranches (\"after true branch\", \"after false branch\") and goes backwards\nfor the last one (usually); e.g. you get a trace for line 20, then 40,\nthen 80, and then suddenly for line 30.\n\nIf this bug bites you there is a simple workaround - just use labels as\njump targets."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.65836}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.658363}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.658365}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.658479}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.658483}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589110973.658485}]
\ No newline at end of file

D .issue/objects/issues/1a/1a7c4657ba9991d6a17349a55d5310033d02fe19/diff/fceb270e9d962c217ec23cf0ad0577be7c87f9a7.json => .issue/objects/issues/1a/1a7c4657ba9991d6a17349a55d5310033d02fe19/diff/fceb270e9d962c217ec23cf0ad0577be7c87f9a7.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.782974}, {"action": "set-message", "params": {"text": "Add \"fast\" versions of call instructions\n\nFor example, a `fast_call` instruction would be used like this:\n\n    fast_call void fn/0 void\n    fast_call void fn/1 %2 local\n\nIt would automatically create a call frame with zero or one parameter\nslot and call the given function using that frame. This means that such\n\"fast\" calls could be executed even if there was a frame already\nprepared.\n\nCall instructions are:\n\n- call\n- tailcall\n- defer\n- process\n- watchdog"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.782983}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.782986}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.78299}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.783111}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.783116}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562417016.78312}]
\ No newline at end of file

D .issue/objects/issues/30/30cf2fb8dd9b184190bbc19c627fa5e351cea5ae/diff/4231488e3ad2d81770af618c25605bc9aa66fdf5.json => .issue/objects/issues/30/30cf2fb8dd9b184190bbc19c627fa5e351cea5ae/diff/4231488e3ad2d81770af618c25605bc9aa66fdf5.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.301967}, {"action": "set-message", "params": {"text": "Fix warnings raised by ThreadSanitizer\n\nRunning Viua test suite with Clang's TSan enabled must not produce any errors."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.301987}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.301994}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.301999}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.302292}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.302301}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.302308}, {"action": "parameter-set", "params": {"key": "github_issue_no", "value": "174"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1493112205.302425}]
\ No newline at end of file

D .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/6508044eecb9455bc53fb1a09a0aa619f42496f1f091aadb76f6e45e76c07064363cbd364e69249f22f5e0584c7399a1.json => .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/6508044eecb9455bc53fb1a09a0aa619f42496f1f091aadb76f6e45e76c07064363cbd364e69249f22f5e0584c7399a1.json +0 -1
@@ 1,1 0,0 @@
[{"action": "set-parent", "params": {"uid": "ae694ea4b60552191e8e49d2c10f0a8cb58a409a2f5c7e9d242edf22b70b9b42b32ac0b4f3a32049f7f8d0ce275d9d3c"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590407}]
\ No newline at end of file

D .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/7c9a092b208585e63d313a4c236af62e7a86ae6c167ddfed862e3c375c159e8a14fd5e71e5dc69cf50093e14c27edd76.json => .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/7c9a092b208585e63d313a4c236af62e7a86ae6c167ddfed862e3c375c159e8a14fd5e71e5dc69cf50093e14c27edd76.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590056}, {"action": "set-message", "params": {"text": "Use big endian for non-address integers in operands\n\nAddresses need more work to implement so get the low-hanging fruit\nfirst."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590064}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590067}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590069}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590176}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.59018}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899196.590182}]
\ No newline at end of file

D .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/a56dd789d799946db6e2dc77a9aaa0807d89668c63777333138fb5ca26a37f48469121d4d3a9f3cb8311664c6ede7215.json => .issue/objects/issues/3a/3ae3c15e094a448bc5889bd982fb7caa373803b7c7ad2f2f216a770141e8bf0b4bd97837795e6692ef26d0201c3bb215/diff/a56dd789d799946db6e2dc77a9aaa0807d89668c63777333138fb5ca26a37f48469121d4d3a9f3cb8311664c6ede7215.json +0 -1
@@ 1,1 0,0 @@
[{"action": "close", "params": {"closing_git_commit": "f4758eb74a7a717ae12a0c46e013dbd2247ab205"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584896928.0}]
\ No newline at end of file

D .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/1074de16304666e5b4536e688d0fff9b2a57482c53cd7c809d8aad6261c7f27e1762cc502a0681ed5c300c7e2fdb34a3.json => .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/1074de16304666e5b4536e688d0fff9b2a57482c53cd7c809d8aad6261c7f27e1762cc502a0681ed5c300c7e2fdb34a3.json +0 -1
@@ 1,1 0,0 @@
[{"action": "close", "params": {"closing_git_commit": "c581cad629f20f15bc8c5aadb0d4a3679855b979"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584898785.0}]
\ No newline at end of file

D .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/739e28a00a53c63548f80db8d9743455799534dc1caf8a9e1b7b3cadda54bd5838d3771728d66be96a3b3ff3a99a58c6.json => .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/739e28a00a53c63548f80db8d9743455799534dc1caf8a9e1b7b3cadda54bd5838d3771728d66be96a3b3ff3a99a58c6.json +0 -1
@@ 1,1 0,0 @@
[{"action": "set-parent", "params": {"uid": "ae694ea4b60552191e8e49d2c10f0a8cb58a409a2f5c7e9d242edf22b70b9b42b32ac0b4f3a32049f7f8d0ce275d9d3c"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429565}]
\ No newline at end of file

D .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/8473d2abca3c84f6af2204920544b03722c2f44cfa14711ed2dd38f1c751a1e0b3a55da45013cb56c0d855591a493148.json => .issue/objects/issues/48/4882be24fccf5c9de2722d8927e5f9b9f69ac122da964658effb2b3184f6a270d3ee8bfbf1fbfe75b1cd59ed6b6dddc8/diff/8473d2abca3c84f6af2204920544b03722c2f44cfa14711ed2dd38f1c751a1e0b3a55da45013cb56c0d855591a493148.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429276}, {"action": "set-message", "params": {"text": "Use big-endian for addresses in operands\n\nThere are still integers in metadata, but we are not interested in\nchanging them... yet."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429284}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429286}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429288}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429382}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429386}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899444.429388}]
\ No newline at end of file

D .issue/objects/issues/4f/4fecd9277051fd84bd63329b43083550bf73d67b/diff/7ed97c23de5adc94cbeb126df2af833ff7559e5b.json => .issue/objects/issues/4f/4fecd9277051fd84bd63329b43083550bf73d67b/diff/7ed97c23de5adc94cbeb126df2af833ff7559e5b.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.71086}, {"action": "set-message", "params": {"text": "Rework assembler and disassembler\n\nThe amount of work that is needed to add a new instruction is\nridiculous. The assembler is actually one of the oldest parts of the\ncodebase has almost not changed since the dawn of the time... which was\nabout 4 years ago. Frankly, I was a pretty poor programmer back then and\ndidn't know shit about how to go about creating VMs or compiler\npipelines. I guess now I'm only marginally better but the bad joke that\nis the assembler is no longer funny and I just can't bear looking at it\nany longer.\n\nTime for a TOTAL REWRITE!"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.710869}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.710872}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.710876}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.711006}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.711011}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1562511271.711015}]
\ No newline at end of file

D .issue/objects/issues/50/505732b9905aae8656f94b9f45847fa91ce55c7b/diff/3c73126ab375f439a2524b09ed875680a3099fb7.json => .issue/objects/issues/50/505732b9905aae8656f94b9f45847fa91ce55c7b/diff/3c73126ab375f439a2524b09ed875680a3099fb7.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.902054}, {"action": "set-message", "params": {"text": "Fix SA for unused registers and values after if instructions\n\nSA will not detect unused registers if both branches have different\nunused values. This is because the check_for_unused_*() functions\nare called as a part of check_register_usage_for_instruction_block_impl()\ninstead of after it - thus an exception thrown for an unused value\nprevents checking for unused registers (they are called sequentially)."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.902072}, {"action": "push-tags", "params": {"tags": ["bug"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.902078}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.902082}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.902351}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.902362}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1530996629.90237}]
\ No newline at end of file

D .issue/objects/issues/60/607b9619609c0f442a1f222c6b36c0e3f84a325e/diff/d753bf4760638bf07e24b14fad0d02e41ee2aa5d.json => .issue/objects/issues/60/607b9619609c0f442a1f222c6b36c0e3f84a325e/diff/d753bf4760638bf07e24b14fad0d02e41ee2aa5d.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995594}, {"action": "set-message", "params": {"text": "Refactor src/cg/tools.cpp\n\nThis file needs some serious refactoring, as the amount of repetition is\nstaggering."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995605}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995609}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995612}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995712}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995715}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1521215562.995721}]
\ No newline at end of file

A .issue/objects/issues/62/6223d3b5cec5343dc8444eb2f95b08ebb7621a5f2d4f919cac6f577e8836eacb81eddf17238efccae132811ce5781204/diff/158db5c6ad7fd174f649f44860aa9e34cbe3cae55420bcba101ecb1fd21a13d7906829d27f13bf7235e18b4b469fade9.json => .issue/objects/issues/62/6223d3b5cec5343dc8444eb2f95b08ebb7621a5f2d4f919cac6f577e8836eacb81eddf17238efccae132811ce5781204/diff/158db5c6ad7fd174f649f44860aa9e34cbe3cae55420bcba101ecb1fd21a13d7906829d27f13bf7235e18b4b469fade9.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.652403}, {"action": "set-message", "params": {"text": "Make all exceptions carry throw points\n\nThe VM supports throwing arbitrary values as exceptions. This is cool\nbut means that we cannot guarantee that every thrown value has a list of\nthrow points attached. In order to guarantee this every thrown value\nwill be wrapped in an exception value that *is* able to carry throw\npoints."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.65241}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.652413}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.652415}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.652529}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.652534}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969248.652537}]
\ No newline at end of file

A .issue/objects/issues/62/6223d3b5cec5343dc8444eb2f95b08ebb7621a5f2d4f919cac6f577e8836eacb81eddf17238efccae132811ce5781204/diff/983456ab672f0dfc8454f3b4527c193c4cafa63d35d5c6b3e87baeac2af41bdef82e1295d21465ad0d97143533cb3e59.json => .issue/objects/issues/62/6223d3b5cec5343dc8444eb2f95b08ebb7621a5f2d4f919cac6f577e8836eacb81eddf17238efccae132811ce5781204/diff/983456ab672f0dfc8454f3b4527c193c4cafa63d35d5c6b3e87baeac2af41bdef82e1295d21465ad0d97143533cb3e59.json +1 -0
@@ 0,0 1,1 @@
[{"action": "close", "params": {}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1586969442.510912}]
\ No newline at end of file

D .issue/objects/issues/65/65debffc0067bf56000dd29de193435df27f27a5f0414493a14af77be002f5a036f41560e160ccd5ebad3fe0563fe688/diff/49b1aafa0b570363977db6cf622a8541040ffa7fa7a20d9ed277d8f34b34074d4aa5d22540bc9222c331937041f167f3.json => .issue/objects/issues/65/65debffc0067bf56000dd29de193435df27f27a5f0414493a14af77be002f5a036f41560e160ccd5ebad3fe0563fe688/diff/49b1aafa0b570363977db6cf622a8541040ffa7fa7a20d9ed277d8f34b34074d4aa5d22540bc9222c331937041f167f3.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.803969}, {"action": "set-message", "params": {"text": "Use big-endian for metadata integers"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.803978}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.803981}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.803983}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.80409}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.804094}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.804096}]
\ No newline at end of file

D .issue/objects/issues/65/65debffc0067bf56000dd29de193435df27f27a5f0414493a14af77be002f5a036f41560e160ccd5ebad3fe0563fe688/diff/7162b9b34cc0f91d9d4fbd840c339024c336d5f10a16ce2304d7d0b02338c397a2b5bcfc1850f9b5509229d802bbe98f.json => .issue/objects/issues/65/65debffc0067bf56000dd29de193435df27f27a5f0414493a14af77be002f5a036f41560e160ccd5ebad3fe0563fe688/diff/7162b9b34cc0f91d9d4fbd840c339024c336d5f10a16ce2304d7d0b02338c397a2b5bcfc1850f9b5509229d802bbe98f.json +0 -1
@@ 1,1 0,0 @@
[{"action": "set-parent", "params": {"uid": "ae694ea4b60552191e8e49d2c10f0a8cb58a409a2f5c7e9d242edf22b70b9b42b32ac0b4f3a32049f7f8d0ce275d9d3c"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1584899458.804307}]
\ No newline at end of file

A .issue/objects/issues/6f/6fd00ea0caf449f20da20383460bce952ea99529b88fe80a51490927934df2a0ac3e367880a05bb6994f023b4be9bd5c/diff/76af2459658effe182eff026c6269ab7d49d35557290fa887ffc7b5e90f2003740c4122ad87e0e6766da54e0ac8f7178.json => .issue/objects/issues/6f/6fd00ea0caf449f20da20383460bce952ea99529b88fe80a51490927934df2a0ac3e367880a05bb6994f023b4be9bd5c/diff/76af2459658effe182eff026c6269ab7d49d35557290fa887ffc7b5e90f2003740c4122ad87e0e6766da54e0ac8f7178.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.087682}, {"action": "set-message", "params": {"text": "Only throw exceptions\n\nIf any Value that is not an exception is thrown just turn it into an\nException."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.08769}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.087693}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.087695}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.087802}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.087806}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592595855.087809}]
\ No newline at end of file

A .issue/objects/issues/79/7935629c4422450d6e6eefaad96cb28a97a580ae8b71e268bcaf384a5eb3536bcc49ecd2dea36d862c2d6653a0701d66/diff/77af79f68bc221659d526b7311531ea386179b83ec7b67c501f7d2e799761ed246b4292f792430d95066717ce4993ffb.json => .issue/objects/issues/79/7935629c4422450d6e6eefaad96cb28a97a580ae8b71e268bcaf384a5eb3536bcc49ecd2dea36d862c2d6653a0701d66/diff/77af79f68bc221659d526b7311531ea386179b83ec7b67c501f7d2e799761ed246b4292f792430d95066717ce4993ffb.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.974918}, {"action": "set-message", "params": {"text": "Implement spaceship operator for comparable types\n\nA C++20 feature that should make it easier to implement reliable\ncomparison operators."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.974925}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.974927}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.974928}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.97501}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.975013}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428360.975015}]
\ No newline at end of file

D .issue/objects/issues/85/85aae918a0330e72f342289888a8242b23ef42e1/diff/a4db927ef493c87d2ed4ef9999981093348bca0a.json => .issue/objects/issues/85/85aae918a0330e72f342289888a8242b23ef42e1/diff/a4db927ef493c87d2ed4ef9999981093348bca0a.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.163714}, {"action": "set-message", "params": {"text": "Allow dynamic timeouts\n\nViua should allow specifying dynamic timeouts.\nCurrently only static timeouts are possible to specify.\n\nAllowing dynamic timeouts means that receive and join instructions\nwould have to support fetching timeouts from registers.\n\nQuestion: should a special Timeout type be introduced, or\nmay timeouts be specified by plain integers?\nWhat about arbitrarily-sized integers?"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.163733}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.163739}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.163744}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.164006}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.164013}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.164021}, {"action": "parameter-set", "params": {"key": "github_issue_no", "value": "181"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194877.164129}]
\ No newline at end of file

A .issue/objects/issues/a6/a6e2c20a78cf246810742d4aa8f68538b22117e35db438d705239ad375898d4c243648ea2ea1889e1369a663660331f6/diff/6c335e6f34dc6e466ef746773c9e3657a352417e391d0125c8ea5eb4544f3d643b76a51588b33f2f193ce78131cc852d.json => .issue/objects/issues/a6/a6e2c20a78cf246810742d4aa8f68538b22117e35db438d705239ad375898d4c243648ea2ea1889e1369a663660331f6/diff/6c335e6f34dc6e466ef746773c9e3657a352417e391d0125c8ea5eb4544f3d643b76a51588b33f2f193ce78131cc852d.json +1 -0
@@ 0,0 1,1 @@
[{"action": "close", "params": {"closing_git_commit": "adea78562c6805d0e38b9258251d00d42bb54c9a"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589124263.0}]
\ No newline at end of file

A .issue/objects/issues/a6/a6e2c20a78cf246810742d4aa8f68538b22117e35db438d705239ad375898d4c243648ea2ea1889e1369a663660331f6/diff/7e2c09abfcca56c6e5be1742622482cccb660c75096350867962e8bd5919a182a7d5c731b26561b1d034f4ec81036e6a.json => .issue/objects/issues/a6/a6e2c20a78cf246810742d4aa8f68538b22117e35db438d705239ad375898d4c243648ea2ea1889e1369a663660331f6/diff/7e2c09abfcca56c6e5be1742622482cccb660c75096350867962e8bd5919a182a7d5c731b26561b1d034f4ec81036e6a.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088395}, {"action": "set-message", "params": {"text": "Add exception values\n\nAn exception has a tag and a payload. Throw instruction supports\nthrowing arbitrary values, but creating proper exceptions should be\navailable to user code.\n\nExample - create an exception with payload:\n\n    .name: iota tag\n    .name: iota value\n    .name: iota ex\n\n    atom %tag local 'Some_error'\n    exception %ex local %tag local %value local\n    throw %ex local\n\nExample - create an exception without payload:\n\n    .name: iota tag\n    .name: iota ex\n\n    atom %tag local 'Some_error'\n    exception %ex local %tag local void\n    throw %ex local"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088405}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088408}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088412}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088598}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088603}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1589111291.088607}]
\ No newline at end of file

D .issue/objects/issues/a8/a80c9ec1d1cf8882665871624c020649766bc094/diff/192a3bcfc97184e215cd64896000a4ee702de2c8.json => .issue/objects/issues/a8/a80c9ec1d1cf8882665871624c020649766bc094/diff/192a3bcfc97184e215cd64896000a4ee702de2c8.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.368557}, {"action": "set-message", "params": {"text": "Always use maybe_null_ptr<> and not_null_ptr<> for function signatures with bare pointers\n\nThis will server as documentation, and additional safety measure."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.368578}, {"action": "push-tags", "params": {"tags": ["internals", "wiring", "reliability"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.368584}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.36859}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.36886}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.368868}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500298147.368876}]
\ No newline at end of file

A .issue/objects/issues/aa/aa38113d2188560e87ea097ef005cc9d06fb53421fe08ee1df839dd0c7338668a7d28d4992800e5e3c20235b8a3f47b6/diff/75e1f609f490746809d34efc2a9b5b05e0b7c19b49b812e9d5c45d6a81c5894f5d6cafbe6c78b4a69c8900e36fcd6248.json => .issue/objects/issues/aa/aa38113d2188560e87ea097ef005cc9d06fb53421fe08ee1df839dd0c7338668a7d28d4992800e5e3c20235b8a3f47b6/diff/75e1f609f490746809d34efc2a9b5b05e0b7c19b49b812e9d5c45d6a81c5894f5d6cafbe6c78b4a69c8900e36fcd6248.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893837}, {"action": "set-message", "params": {"text": "Use C++20 to compile VM"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893845}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893847}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893849}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893956}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893959}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428244.893962}]
\ No newline at end of file

D .issue/objects/issues/c4/c4c8625c12bf57c760834eae81dff09daa236528/diff/eaaf7b1199fc957305a4e1da3222f3571c0d7c0b.json => .issue/objects/issues/c4/c4c8625c12bf57c760834eae81dff09daa236528/diff/eaaf7b1199fc957305a4e1da3222f3571c0d7c0b.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.747671}, {"action": "set-message", "params": {"text": "Implement arbitrary width integers\n\nDefault integers should be limited only by available memory.\nSpecialised fixed-width integers should be a separate type."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.747689}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.747698}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.747703}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.747962}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.74797}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.747978}, {"action": "parameter-set", "params": {"key": "github_issue_no", "value": "178"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1499194126.748087}]
\ No newline at end of file

D .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/comments/660c503ee2c7ac985a9bba8b5525ffc9644e68a0.json => .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/comments/660c503ee2c7ac985a9bba8b5525ffc9644e68a0.json +0 -1
@@ 1,1 0,0 @@
{"author.name": "Marek Marecki", "author.email": "marejm@ozro.pw", "message": "Signed fixed-width arithmetic instructions are available in devel branch.\nMaybe a release is in order?", "timestamp": 1512416700.386231}
\ No newline at end of file

D .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/comments/e441d063260914c074b1fa157e0d07b55eefa72b.json => .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/comments/e441d063260914c074b1fa157e0d07b55eefa72b.json +0 -1
@@ 1,1 0,0 @@
{"author.name": "Marek Marecki", "author.email": "marejm@ozro.pw", "message": "Dedicated instructions for fixed-width subtraction should be added to ISA.\nFive new instructions will be needed:\n\n- wrapsub\n- checkedssub\n- checkedusub\n- saturatingssub\n- saturatingusub", "timestamp": 1512416845.105123}
\ No newline at end of file

D .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/diff/a0ca9471d9c87e4758c99bd86a7829cd8f58f33c.json => .issue/objects/issues/e8/e8113638e0ccd5bf7c8378551e0b621541b59f2e/diff/a0ca9471d9c87e4758c99bd86a7829cd8f58f33c.json +0 -1
@@ 1,1 0,0 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.405874}, {"action": "set-message", "params": {"text": "Math on bits"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.405887}, {"action": "push-tags", "params": {"tags": ["enhancement", "feature"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.405891}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.405894}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.406074}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.406079}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1500821087.406086}]
\ No newline at end of file

A .issue/objects/issues/fe/fec884e6c5cb3acbd57905050fa9564d340319558e59d14094b9bc71c47a278427002c0b364b7c32520341689bef5c83/diff/7dcc3af2c8d0336c4e3fbc47d279c07bd52a12a0b27c93d79fbaf98458d56f646df9e952dc5ec025da012d3373ae973c.json => .issue/objects/issues/fe/fec884e6c5cb3acbd57905050fa9564d340319558e59d14094b9bc71c47a278427002c0b364b7c32520341689bef5c83/diff/7dcc3af2c8d0336c4e3fbc47d279c07bd52a12a0b27c93d79fbaf98458d56f646df9e952dc5ec025da012d3373ae973c.json +1 -0
@@ 0,0 1,1 @@
[{"action": "open", "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.885578}, {"action": "set-message", "params": {"text": "Use constexpr std::string for type names of types\n\nCurrently they are char const*."}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.885585}, {"action": "push-tags", "params": {"tags": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.885588}, {"action": "push-milestones", "params": {"milestones": []}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.88559}, {"action": "push-tags", "params": {"tags": ["viuavm"]}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.885696}, {"action": "set-project-tag", "params": {"tag": "viuavm"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.8857}, {"action": "set-project-name", "params": {"name": "Viua Virtual Machine"}, "author": {"author.email": "marejm@ozro.pw", "author.name": "Marek Marecki"}, "timestamp": 1592428275.885702}]
\ No newline at end of file

M Changelog.markdown => Changelog.markdown +90 -10
@@ 8,7 8,7 @@ Changes documented here are not the fullest representation of all changes.
For that you have to reference Git commit log.


----
--------------------------------------------------------------------------------

### Change categories



@@ 25,14 25,94 @@ There are several categories of change:
- **misc**: various other changes not really fitting into any other category,


----
--------------------------------------------------------------------------------

# From 0.10.0 to 0.10.1

- bic: integers are stored in big-endian order in bytecode
- enhancement: stack traces now include exception throw points to make debugging
  easier
- bic: thrown values are wrapped in an exception value and need to be extracted
- feature: user code can throw exceptions with custom tags and values
- feature: user code can extract exception tags using `exception_tag`
  instruction
- feature: user code can extract exception values using `exception_value`
  instruction
- fix: escape sequences in strings are handled correctly (or at least better)
- fix: do not crash when `textat` instruction is used on empty string; throw an
  exception instead
- bic: instead of throwing a generic Exception, pointers now throw
  `Invalid_dereference` (when dereferenced outside of original process) and
  `Expired_pointer`-tagged exceptions when they detect an error during
  dereference
- bic: pointer-tracking works a little bit differently, the change may not be
  entirely backwards compatible

Exceptions now track the points at which they were thrown and rethrown. Rethrows
happen at process join points (i.e. join instructions). Stack trace reports use
this information to show *where* the exception that killed a process was thrown.
It looks like this:

    throw points:
        address: 0x19d2 (byte 6610) inside 0x89dead42beef [a.out::foo/2]
        address: 0x295d (byte 10589) inside 0x89dead42beef [a.out::main/0]

If the failure was really bad the report may look like this:

    throw points:
        address: 0xdead (byte 57005) inside 0xc00ffe [a.out:<outside of executable range>]
        address: 0xbeef (byte 48879) inside 0xf84210 [<unknown>::<unknown>]

----

Previously user code could only throw ordinary values, e.g. integers, strings.
It is now possible for user code to construct exceptions with arbitrarily chosen
tags (atoms) and values. This means that programs running on the VM can
construct any exception they need and have the same power as the VM itself.

An exception is a simple value that carries a tag (which is used to determine
which catch block to use) and an optional value (which may be a description of
the error, an error code, etc.). A new instruction is introduced to allow user
code to construct exceptions; its mnemonic is `exception`.

    .name: iota ex
    .name: iota tag
    .name: iota value

    atom %tag local 'Some_error'
    text %value local "some error occurred"
    exception %ex local %tag local %value local

The example above constructs an exception tagged with `Some_error` and carrying
a description. In the next example a value-less exception is constructed:

    .name: iota ex
    .name: iota tag

    atom %tag local 'Some_error'
    exception %ex local %tag local void

Such an exception does not carry any value and its meaning is conveyed only by
its tag.

To extract a tag of an exception the `exception_tag` instruction is used; to
extract a value the `exception_value` instruction is used. The `exception_value`
instruction is a destructive one - it moves the value out of an exception. If
the exception needs to be rethrown it must be constructed anew.

    .name: iota tag
    .name: iota value
    .name: iota ex

    draw %ex local
    exception_tag %tag local %ex local
    exception_value %value local %ex local

The example above presents `exception_tag` and `exception_value` instructions in
action.

--------------------------------------------------------------------------------

# From 0.9.0 to 0.10.0

- feature: bit manipulation instructions (and, or, xor; arithmetic and logical shifts;


@@ 135,7 215,7 @@ major revamp in the way I/O is performed by programs running on Viua VM.
A dedicated I/O subsystem will free the generic FFI subsystem to do more work
not related to I/O that has to be done outside of the "normal" VM constraints.

----
--------------------------------------------------------------------------------

# From 0.8.4 to 0.9.0



@@ 276,7 356,7 @@ As a feature for contributors, a `.clang-format` has been added to the repositor
ensuring a uniform coding style accross Viua VM source base.


----
--------------------------------------------------------------------------------


# From 0.8.3 to 0.8.4


@@ 290,7 370,7 @@ ensuring a uniform coding style accross Viua VM source base.
- feature: `--json` option in CPU frontend same as `--info` but in JSON format


----
--------------------------------------------------------------------------------


# From 0.8.2 to 0.8.3


@@ 310,7 390,7 @@ ensuring a uniform coding style accross Viua VM source base.
  spawned by default is 2


----
--------------------------------------------------------------------------------


# From 0.8.1 to 0.8.2


@@ 336,7 416,7 @@ concurrent processes running.
- bic: machine exits with non-zero exit code only if the `main/` function fails,


----
--------------------------------------------------------------------------------


# From 0.8.0 to 0.8.1


@@ 384,7 464,7 @@ compilation unit), and some arity errors during function calls.
- enhancement: assembler catches double passes to parameter slotss,


----
--------------------------------------------------------------------------------


# From 0.7.0 to 0.8.0


@@ 435,7 515,7 @@ FFI worker thread for non-blocking calls to foreign functions.
  this way native Viua code is never blocked by an FFI call,


----
--------------------------------------------------------------------------------


# From 0.6.1 to 0.7.0


@@ 449,7 529,7 @@ FFI worker thread for non-blocking calls to foreign functions.
- fix: stack traces displayed after uncaught exceptions are generated for the thread that
  the exception originated from
- bic: machine reports the function that started a thread as orphaning thread's children,
  this means that old "main/1 orphaning threads" changes to "__entry/0 orphaning trhreads"
  this means that old "main/1 orphaning threads" changes to "`__entry/0` orphaning trhreads"
- misc: if stack is not available "<unavailable> (stack empty)" will be used when
  machine reports that threads were orphaned,
- enhancement: returning objects from functions has "move semantics" - there is no copy

M Makefile => Makefile +156 -283
@@ 1,25 1,20 @@
# Clang 4.0 does not recognise -std=c++17 option, and
# needs -std=c++1z.
# Clang 5.0 and later recognises -std=c++17
# See http://clang.llvm.org/cxx_status.html for details.
# See http://clang.llvm.org/cxx_status.html for clang++ details.
CXX_STANDARD=c++17


# By default, try to catch everything.
# This may be painful at first but it pays off in the long run.
GENERIC_SANITISER_FLAGS=-fstack-protector-strong \
						-fsanitize=undefined \
						-fsanitize=leak \
						-fsanitize=address
CLANG_SANITISER_FLAGS=  -fstack-protector-strong \
						-fsanitize=undefined \
						-fsanitize=leak \
						-fsanitize=address
COMMON_SANITISER_FLAGS=\
					   -fstack-protector-strong \
					   -fsanitize=undefined
CLANG_SANITISER_FLAGS=\
					  $(COMMON_SANITISER_FLAGS) \
					  -fsanitize=leak \
					  -fsanitize=address
# No -fsanitize=address for GCC because of too many false positives.
# No -fsanitize=leak for GCC because it broke on my Arch Linux after
# last update.
GCC_SANITISER_FLAGS=    -fstack-protector-strong \
						-fsanitize=undefined
GCC_SANITISER_FLAGS=\
					$(COMMON_SANITISER_FLAGS) \
					-fsanitize=leak


# These are generic flags that should be used for compiling Viua VM.


@@ 32,41 27,16 @@ GCC_SANITISER_FLAGS=    -fstack-protector-strong \
#	-Winline			-- fails if GCC tries to inline calls that are unlikely and
#							the code size would grow
# 	-Wdisabled-optimization	-- some source files are too big
GENERIC_CXXFLAGS=-Wall \
				 -Wextra \
				 -Wctor-dtor-privacy \
				 -Wnon-virtual-dtor \
				 -Wreorder \
				 -Woverloaded-virtual \
				 -Wundef \
				 -Wstrict-overflow=2 \
				 -Winit-self \
				 -Wzero-as-null-pointer-constant \
				 -Wuseless-cast \
				 -Wconversion \
				 -Wshadow \
				 -Wswitch-default \
				 -Wswitch-enum \
				 -Wredundant-decls \
				 -Wlogical-op \
				 -Wmissing-include-dirs \
				 -Wmissing-declarations \
				 -Wcast-align \
				 -Wcast-qual \
				 -Wold-style-cast \
				 -Walloc-zero \
				 -Wdouble-promotion \
				 -Wunused-const-variable=2 \
				 -Wduplicated-branches \
				 -Wduplicated-cond \
				 -Wsign-conversion \
				 -Wrestrict \
				 -Wstack-protector \
				 -Werror \
				 -Wfatal-errors \
				 -Wpedantic \
				 -g \
				 -I./include
INCLUDE_FLAGS=\
			  -I./include
COMMON_CXXFLAGS=\
				-Wall \
				-Wextra \
				-Werror \
				-Wfatal-errors \
				-pedantic \
				-g \
				$(INCLUDE_FLAGS)
# -Weverything						-- in theory enables *everything*
# -Wdeprecated-implementations		-- makes sense for C++?
# -Wpadded							-- breaks existing code


@@ 77,8 47,8 @@ GENERIC_CXXFLAGS=-Wall \
# -Wunused-template					-- breaks existing code
# -Wfloat-equal 					-- breaks existing code
# -Wlifetime						-- would be useful
CLANG_CXXFLAGS=-Wall \
			   -Wextra \
CLANG_CXXFLAGS=\
			   $(COMMON_CXXFLAGS) \
			   -Wabsolute-value \
			   -Wabstract-vbase-init \
			   -Warray-bounds-pointer-arithmetic \


@@ 176,87 146,76 @@ CLANG_CXXFLAGS=-Wall \
			   -Wzero-as-null-pointer-constant \
			   -Wzero-length-array \
			   -Wc++2a-compat \
			   -Werror \
			   -Wno-weak-vtables \
			   -Wfatal-errors \
			   -pedantic \
			   -g \
			   -I./include
GCC_CXXFLAGS=$(GENERIC_CXXFLAGS)
			   $(CLANG_SANITISER_FLAGS)
GCC_CXXFLAGS=\
			 $(COMMON_CXXFLAGS) \
			 -fdiagnostics-color=always \
			 -Wctor-dtor-privacy \
			 -Wnon-virtual-dtor \
			 -Wreorder \
			 -Woverloaded-virtual \
			 -Wundef \
			 -Wstrict-overflow=2 \
			 -Winit-self \
			 -Wzero-as-null-pointer-constant \
			 -Wuseless-cast \
			 -Wconversion \
			 -Wshadow \
			 -Wswitch-default \
			 -Wswitch-enum \
			 -Wredundant-decls \
			 -Wlogical-op \
			 -Wmissing-include-dirs \
			 -Wmissing-declarations \
			 -Wcast-align \
			 -Wcast-qual \
			 -Wold-style-cast \
			 -Walloc-zero \
			 -Wdouble-promotion \
			 -Wunused-const-variable=2 \
			 -Wduplicated-branches \
			 -Wduplicated-cond \
			 -Wsign-conversion \
			 -Wrestrict \
			 -Wstack-protector \
			 $(GCC_SANITISER_FLAGS)


# For different compilers (and for TravisCI) compiler flags should be overridden, because
# of throwing too many false positives or being unsupported.
# If any compiler that should be treated specially is detected, CXXFLAGS is adjusted for its (the
# compiler's) needs; otherwise, generic CXXFLAGS are used.
#
# The process of setting CXXFLAGS in a multi-phase one.
# There are several things that need to be decided on:
# - the C++ standard to be used
# - the set of warning flags
# - the set of sanitiser flags
# - optimisation level
#
# After all this parts are set, Make will compose the final CXXFLAGS.

# By default, use generic flags.
SANITISER_FLAGS=$(GENERIC_SANITISER_FLAGS)
COMPILER_FLAGS=$(GENERIC_CXXFLAGS)

ifeq ($(CXX), g++)
COMPILER_FLAGS=$(GENERIC_CXXFLAGS) \
COMPILER_FLAGS=$(GCC_CXXFLAGS) \
			   --param max-gcse-memory=134217728
			   #--param max-gcse-memory=67108864
SANITISER_FLAGS=$(GCC_SANITISER_FLAGS)
else ifeq ($(CXX), g++-7)
COMPILER_FLAGS=-Wall \
			   -Wextra \
			   -Wzero-as-null-pointer-constant \
			   -Wuseless-cast \
			   -Wconversion \
			   -Wshadow \
			   -Wswitch-default \
			   -Wredundant-decls \
			   -Wlogical-op \
			   -Wmissing-include-dirs \
			   -Wcast-align \
			   -Wold-style-cast \
			   -Werror \
			   -Wfatal-errors \
			   -pedantic \
			   -g \
			   -I./include
SANITISER_FLAGS=-fsanitize=undefined
else ifeq ($(CXX), clang++)
COMPILER_FLAGS=$(CLANG_CXXFLAGS)
else ifeq ($(CXX), clang++-5.0)
COMPILER_FLAGS=$(CLANG_CXXFLAGS)
SANITISER_FLAGS=-fsanitize=undefined \
				-fstack-protector-strong \
				-fsanitize=address
endif

# Combine compiler and sanitiser flags, and used C++ standard into final CXXFLAGS.
# CXX_EXTRA_FLAGS are meant to be supplied on the command line.
# By default, the VM is compiled using no optimisations. This makes for shorter
# compile times and better debugging experience, but prevents speed-testing the
# VM. For even better debugging - use 'g' (as if -Og) value.
#
# You should run the VM with -O3 every once in a while to see how it's doing.
#
OPTIMISATION_LEVEL=0
OPTIMISATION_FLAG=-O$(OPTIMISATION_LEVEL)

# Build information includes commit from which the VM was built and a hash of
# the code (this is for development builds as commit and version stays the same
# for them). These two pieces of information stay constant and depend only on
# the code.
# If we were to include build date in build information embedded in Viua VM
# executables it should be presented this way: date --rfc-3339 ns
CXXFLAGS=\
		 -std=$(CXX_STANDARD) \
		 -DVIUA_VM_COMMIT="\"$(shell ./scripts/get_head_commit.sh)\"" \
		 -DVIUA_VM_COMMIT="\"$(shell bash ./scripts/get_head_commit.sh)\"" \
		 -DVIUA_VM_CODE_FINGERPRINT="\"$(shell bash ./scripts/get_code_fingerprint.sh)\"" \
		 $(COMPILER_FLAGS) \
		 $(SANITISER_FLAGS) \
		 $(CXX_EXTRA_FLAGS)

# By default, the VM is compiled using no optimisations.
# This makes for shorter compile times, but prevents speed-testing the VM.
# You should run the VM with -O3 every once in a while to see how it's doing.
CXXOPTIMIZATIONFLAGS=-O0
COPTIMIZATIONFLAGS=
		 $(OPTIMISATION_FLAG)

# Expose symbols in the VM kernel binary to the shared libraries that are linked at runtime.
# It is done this way to avoid making every library carry its own copy of functions used to access
# registers, types, the kernel, etc.
# I don't yet know how this will affect library compatibility. Runtime crashes because a symbol has
# been moved? Shouldn't happen because the symbol will be located dynamically.
# I guess we'll see.
# been moved? Shouldn't happen because the symbol will be located dynamically. I guess we'll see.
DYNAMIC_SYMS=-Wl,--dynamic-list-cpp-typeinfo -rdynamic




@@ 268,18 227,25 @@ LDLIBS=-ldl -lpthread

.SUFFIXES: .cpp .h .o

.PHONY: all remake clean clean-support clean-test-compiles install compile-test test version platform
.PHONY: \
	all \
	clean \
	clean-support \
	clean-test-compiles \
	compile-test \
	install \
	remake \
	test \
	version


############################################################
# BASICS
all: build/bin/vm/asm \
all: \
	build/bin/vm/asm \
	build/bin/vm/kernel \
	build/bin/vm/dis \
	build/bin/vm/lex \
	build/bin/vm/parser \
	build/bin/opcodes.bin \
	platform \
	stdlib \
	standardlibrary \
	compile-test \


@@ 310,30 276,31 @@ clean-test-compiles:

############################################################
# INSTALLATION AND UNINSTALLATION
bininstall: build/bin/vm/asm \
	build/bin/vm/kernel \
	build/bin/vm/dis
	mkdir -p $(BIN_PATH)
	cp ./build/bin/vm/asm $(BIN_PATH)/viua-asm
	chmod 755 $(BIN_PATH)/viua-asm
	cp ./build/bin/vm/kernel $(BIN_PATH)/viua-vm
	chmod 755 $(BIN_PATH)/viua-vm
	cp ./build/bin/vm/dis $(BIN_PATH)/viua-dis
	chmod 755 $(BIN_PATH)/viua-dis

libinstall: stdlib
	mkdir -p $(LIB_PATH)/std
	mkdir -p $(LIB_PATH)/std/posix
	cp ./build/stdlib/std/*.so $(LIB_PATH)/std
	cp ./build/stdlib/std/posix/*.so $(LIB_PATH)/std/posix

installdevel: platform
	mkdir -p $(LIB_PATH)/platform
	cp ./build/platform/*.o $(LIB_PATH)/platform

install: bininstall libinstall
	mkdir -p $(H_PATH)
	cp -R ./include/viua/. $(H_PATH)/
install-execs: \
	build/bin/vm/asm \
	build/bin/vm/dis \
	build/bin/vm/kernel
	@mkdir -p $(BIN_PATH)
	@cp -v ./build/bin/vm/asm $(BIN_PATH)/viua-asm
	@chmod 755 $(BIN_PATH)/viua-asm
	@cp -v ./build/bin/vm/kernel $(BIN_PATH)/viua-vm
	@chmod 755 $(BIN_PATH)/viua-vm
	@cp -v ./build/bin/vm/dis $(BIN_PATH)/viua-dis
	@chmod 755 $(BIN_PATH)/viua-dis

install-libs: stdlib
	@mkdir -p $(LIB_PATH)/std
	@mkdir -p $(LIB_PATH)/std/posix
	@cp ./build/stdlib/std/*.so $(LIB_PATH)/std
	@cp ./build/stdlib/std/posix/*.so $(LIB_PATH)/std/posix

install-headers:
	# mkdir -p $(H_PATH)
	# cp -R ./include/viua/. $(H_PATH)/

install: \
	install-execs \
	install-libs

uninstall:
	rm -rf $(H_PATH)


@@ 342,61 309,9 @@ uninstall:


############################################################
# PLATFORM OBJECT FILES
platform: build/platform/types/exception.o \
	build/platform/types/value.o \
	build/platform/types/pointer.o \
	build/platform/types/number.o \
	build/platform/types/integer.o \
	build/platform/types/io.o \
	build/platform/types/bits.o \
	build/platform/types/float.o \
	build/platform/types/string.o \
	build/platform/types/atom.o \
	build/platform/types/struct.o \
	build/platform/types/text.o \
	build/platform/types/vector.o \
	build/platform/types/reference.o \
	build/platform/kernel/registerset.o \
	build/platform/support/string.o

build/platform/kernel/registerset.o: src/kernel/registerset.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -o $@ $<

build/platform/support/string.o: src/support/string.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -o $@ $<


############################################################
# TESTING
build/test/printer.so: build/test/printer.o \
	build/platform/kernel/registerset.o \
	build/platform/types/value.o \
	build/platform/types/exception.o

build/test/sleeper.so: build/test/sleeper.o \
	build/platform/kernel/registerset.o \
	build/platform/types/value.o \
	build/platform/types/exception.o

build/test/math.so: build/test/math.o \
	build/platform/kernel/registerset.o \
	build/platform/types/exception.o \
	build/platform/types/value.o \
	build/platform/types/pointer.o \
	build/platform/types/integer.o \
	build/platform/types/float.o \
	build/platform/types/number.o

build/test/throwing.so: build/test/throwing.o \
	build/platform/kernel/registerset.o \
	build/platform/types/exception.o \
	build/platform/types/value.o \
	build/platform/types/pointer.o \
	build/platform/types/integer.o \
	build/platform/types/number.o

compile-test: build/test/math.so \
compile-test: \
	build/test/math.so \
	build/test/World.so \
	build/test/throwing.so \
	build/test/printer.so \


@@ 430,57 345,29 @@ tools: build/bin/tools/log-shortener

############################################################
# RULES
build/platform/types/%.o: src/types/%.cpp include/viua/types/%.h
	$(CXX) $(CXXFLAGS) -fPIC -c -o $@ $<

build/platform/%.o: src/%.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -o $@ $<

build/test/%.o: sample/asm/external/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -fPIC -o $@ $<
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -fPIC -c -o $@ $<

build/test/%.so: build/test/%.o
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -fPIC -shared -o $@ $^

build/front/asm/%.o: src/front/asm/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<

build/front/%.o: src/front/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -fPIC -shared -o $@ $^

build/%.o: src/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<

build/scheduler/%.o: src/scheduler/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $^

build/kernel/%.o: src/kernel/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) -c -o $@ $<

build/stdlib/std/%.module: src/stdlib/viua/%.asm build/bin/vm/asm
	./build/bin/vm/asm --lib -o $@ $<

build/stdlib/std/%.o: src/stdlib/%.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -I./include -o $@ $<
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) -fPIC -c -o $@ $<

# FIXME what about -Wl,--no-undefined ?
build/stdlib/std/%.so: build/stdlib/std/%.o
	$(CXX) $(CXXFLAGS) -fPIC -shared -o $@ $^
	# $(CXX) $(CXXFLAGS) -Wl,--no-undefined -fPIC -shared -o $@ $^

build/types/%.o: src/types/%.cpp include/viua/types/%.h
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<

build/process/instr/%.o: src/process/instr/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<

build/support/%.o: src/support/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<

build/assembler/%.o: src/assembler/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<

build/cg/%.o: src/cg/%.cpp
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -c -o $@ $<
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) -fPIC -shared -o $@ $^


############################################################


@@ 506,7 393,8 @@ VIUA_INSTR_FILES_O=\
				   build/process/instr/text.o \
				   build/process/instr/vector.o

VIUA_TYPES_FILES_O=build/types/atom.o \
VIUA_TYPES_FILES_O=\
				   build/types/atom.o \
				   build/types/bits.o \
				   build/types/boolean.o \
				   build/types/closure.o \


@@ 516,7 404,6 @@ VIUA_TYPES_FILES_O=build/types/atom.o \
				   build/types/integer.o \
				   build/types/io.o \
				   build/types/number.o \
				   build/types/object.o \
				   build/types/pointer.o \
				   build/types/process.o \
				   build/types/reference.o \


@@ 549,6 436,7 @@ build/bin/vm/kernel: \
	build/support/pointer.o \
	build/support/string.o \
	build/support/env.o \
	build/util/string/ops.o \
	$(VIUA_INSTR_FILES_O) \
	$(VIUA_TYPES_FILES_O) \
	build/cg/disassembler/disassembler.o \


@@ 556,7 444,8 @@ build/bin/vm/kernel: \
	build/cg/lex.o \
	build/cg/lex/reduce_fns.o \
	build/cg/lex/cook.o
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^ $(LDLIBS)
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(DYNAMIC_SYMS) -o $@ $^ $(LDLIBS)

OP_ASSEMBLERS= \
	build/assembler/backend/op_assemblers/assemble_op_bits.o \


@@ 637,6 526,9 @@ build/bin/vm/asm: build/front/asm.o \
	build/assembler/frontend/static_analyser/checkers/check_op_delete.o \
	build/assembler/frontend/static_analyser/checkers/check_op_draw.o \
	build/assembler/frontend/static_analyser/checkers/check_op_enter.o \
	build/assembler/frontend/static_analyser/checkers/check_op_exception.o \
	build/assembler/frontend/static_analyser/checkers/check_op_exception_tag.o \
	build/assembler/frontend/static_analyser/checkers/check_op_exception_value.o \
	build/assembler/frontend/static_analyser/checkers/check_op_float.o \
	build/assembler/frontend/static_analyser/checkers/check_op_frame.o \
	build/assembler/frontend/static_analyser/checkers/check_op_ftoi.o \


@@ 697,7 589,8 @@ build/bin/vm/asm: build/front/asm.o \
	build/assembler/frontend/static_analyser/Closure.o \
	build/assembler/frontend/static_analyser/Register_usage_profile.o \
	build/assembler/util/pretty_printer.o
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^ -lpthread

build/bin/vm/lex: build/front/lexer.o \
	build/cg/lex.o \


@@ 707,7 600,8 @@ build/bin/vm/lex: build/front/lexer.o \
	build/support/string.o \
	build/support/env.o \
	build/cg/assembler/binary_literals.o
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^

build/bin/vm/parser: build/front/parser.o \
	build/cg/lex.o \


@@ 721,7 615,8 @@ build/bin/vm/parser: build/front/parser.o \
	build/assembler/frontend/parser.o \
	build/assembler/frontend/static_analyser/verifier.o \
	build/assembler/util/pretty_printer.o
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^

build/bin/vm/dis: build/front/dis.o \
	build/loader.o \


@@ 733,7 628,8 @@ build/bin/vm/dis: build/front/dis.o \
	build/cg/assembler/utils.o \
	build/assembler/util/pretty_printer.o \
	build/cg/lex.o
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^
	@echo "$(CXX) -> $@"
	@$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) $(DYNAMIC_SYMS) -o $@ $^


############################################################


@@ 789,62 685,39 @@ stdlib: build/bin/vm/asm \
	build/stdlib/Std/Random.so \
	build/stdlib/std/kitchensink.so

####
#### Fix for Travis CI.
#### Once GNU Make is upgraded to 4.2 or later, these targets will not
#### be needed.
####
build/stdlib/std/typesystem.o: src/stdlib/typesystem.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -I./include -o $@ $<

build/stdlib/std/os.o: src/stdlib/os.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -I./include -o $@ $<

build/stdlib/std/io.o: src/stdlib/io.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -I./include -o $@ $<

build/stdlib/std/random.o: src/stdlib/random.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -I./include -o $@ $<

build/stdlib/std/kitchensink.o: src/stdlib/kitchensink.cpp
	$(CXX) $(CXXFLAGS) -fPIC -c -I./include -o $@ $<
####
#### End of fix for Travis CI.
####

build/stdlib/std/typesystem.so: build/stdlib/std/typesystem.o

build/stdlib/std/os.so: build/stdlib/std/os.o

build/stdlib/std/io.so: build/stdlib/std/io.o

build/stdlib/std/posix/network.so: build/stdlib/std/posix/network.o
build/stdlib/std/kitchensink.so: build/stdlib/std/kitchensink.o
build/stdlib/std/os.so: build/stdlib/std/os.o
build/stdlib/std/posix/io.so: build/stdlib/std/posix/io.o

build/stdlib/std/posix/network.so: build/stdlib/std/posix/network.o
build/stdlib/std/random.so: build/stdlib/std/random.o

build/stdlib/std/kitchensink.so: build/stdlib/std/kitchensink.o
build/stdlib/std/typesystem.so: build/stdlib/std/typesystem.o


############################################################
# OPCODE LISTER PROGRAM
build/bin/opcodes.bin: src/bytecode/opcd.cpp \
build/bin/opcodes.bin: \
	src/bytecode/opcd.cpp \
	include/viua/bytecode/opcodes.h \
	include/viua/bytecode/maps.h
	$(CXX) $(CXXFLAGS) $(CXXOPTIMIZATIONFLAGS) -o $@ $<
	$(CXX) $(CXXFLAGS) -o $@ $<


############################################################
# DEPENDENCY LIBRARIES
build/lib/linenoise.o: lib/linenoise/linenoise.c lib/linenoise/linenoise.h
build/lib/linenoise.o: \
	lib/linenoise/linenoise.c \
	lib/linenoise/linenoise.h
	$(CC) $(CFLAGS) $(COPTIMIZATIONFLAGS) -c -o $@ $<


#######################################################################
# TOOLING
tooling: build/tooling/exec/assembler.bin
tooling: \
	build/tooling/exec/assembler.bin

build/tooling/libs/lexer/tokenise.o: build/tooling/libs/lexer/normaliser.o
build/tooling/libs/lexer/tokenise.o: \
	build/tooling/libs/lexer/normaliser.o
build/tooling/exec/assembler.bin: \
	build/tooling/exec/assembler/main.o \
	build/tooling/errors/compile_time.o \

M include/viua/assembler/backend/op_assemblers.h => include/viua/assembler/backend/op_assemblers.h +48 -47
@@ 21,6 21,7 @@
#define VIUA_ASSEMBLER_BACKEND_OP_ASSEMBLERS_H

#include <vector>

#include <viua/cg/assembler/assembler.h>
#include <viua/cg/lex.h>
#include <viua/program.h>


@@ 53,13 54,13 @@ auto assemble_double_register_op(Program& program,
    Token_index target = i + 1;
    Token_index source = target + 2;

    (program
     .*op)(::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(target)),
               ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(source)),
               ::assembler::operands::resolve_rs_type(tokens.at(source + 1))));
    (program.*op)(
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(target)),
            ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(source)),
            ::assembler::operands::resolve_rs_type(tokens.at(source + 1))));
}

using Three_register_op = Program& (Program::*)(int_op, int_op, int_op);


@@ 72,16 73,16 @@ auto assemble_three_register_op(Program& program,
    Token_index lhs    = target + 2;
    Token_index rhs    = lhs + 2;

    (program
     .*op)(::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(target)),
               ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(lhs)),
               ::assembler::operands::resolve_rs_type(tokens.at(lhs + 1))),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(rhs)),
               ::assembler::operands::resolve_rs_type(tokens.at(rhs + 1))));
    (program.*op)(
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(target)),
            ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(lhs)),
            ::assembler::operands::resolve_rs_type(tokens.at(lhs + 1))),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(rhs)),
            ::assembler::operands::resolve_rs_type(tokens.at(rhs + 1))));
}

using Four_register_op = Program& (Program::*)(int_op, int_op, int_op, int_op);


@@ 141,11 142,11 @@ auto assemble_fn_ctor_op(Program& program,
    Token_index target = i + 1;
    Token_index source = target + 2;

    (program
     .*op)(::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(target)),
               ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
           tokens.at(source));
    (program.*op)(
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(target)),
            ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
        tokens.at(source));
}

using No_result_name_call_op  = Program& (Program::*)(int_op);


@@ 175,13 176,13 @@ auto assemble_parameter_op(Program& program,
    Token_index target = i + 1;
    Token_index source = target + 1;

    (program
     .*op)(::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(target)),
               viua::bytecode::codec::Register_set::Arguments),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(source)),
               ::assembler::operands::resolve_rs_type(tokens.at(source + 1))));
    (program.*op)(
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(target)),
            viua::bytecode::codec::Register_set::Arguments),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(source)),
            ::assembler::operands::resolve_rs_type(tokens.at(source + 1))));
}

using ShiftOp = Program& (Program::*)(int_op, int_op, int_op);


@@ 206,14 207,14 @@ auto assemble_bit_shift_instruction(Program& program,
            ::assembler::operands::resolve_rs_type(tokens.at(target + 1)));
    }

    (program
     .*op)(ret,
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(lhs)),
               ::assembler::operands::resolve_rs_type(tokens.at(lhs + 1))),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(rhs)),
               ::assembler::operands::resolve_rs_type(tokens.at(rhs + 1))));
    (program.*op)(
        ret,
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(lhs)),
            ::assembler::operands::resolve_rs_type(tokens.at(lhs + 1))),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(rhs)),
            ::assembler::operands::resolve_rs_type(tokens.at(rhs + 1))));
}

using IncrementOp = Program& (Program::*)(int_op);


@@ 239,16 240,16 @@ auto assemble_arithmetic_instruction(Program& program,
    Token_index lhs    = target + 2;
    Token_index rhs    = lhs + 2;

    (program
     .*op)(::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(target)),
               ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(lhs)),
               ::assembler::operands::resolve_rs_type(tokens.at(lhs + 1))),
           ::assembler::operands::getint_with_rs_type(
               ::assembler::operands::resolve_register(tokens.at(rhs)),
               ::assembler::operands::resolve_rs_type(tokens.at(rhs + 1))));
    (program.*op)(
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(target)),
            ::assembler::operands::resolve_rs_type(tokens.at(target + 1))),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(lhs)),
            ::assembler::operands::resolve_rs_type(tokens.at(lhs + 1))),
        ::assembler::operands::getint_with_rs_type(
            ::assembler::operands::resolve_register(tokens.at(rhs)),
            ::assembler::operands::resolve_rs_type(tokens.at(rhs + 1))));
}

auto assemble_op_integer(Program&, std::vector<Token> const&, Token_index const)

M include/viua/assembler/frontend/parser.h => include/viua/assembler/frontend/parser.h +5 -1
@@ 24,6 24,7 @@
#include <memory>
#include <string>
#include <vector>

#include <viua/bytecode/bytetypedef.h>
#include <viua/bytecode/opcodes.h>
#include <viua/bytecode/operand_types.h>


@@ 147,7 148,10 @@ template<typename T> class vector_view {
    {
        return vec.at(offset + i);
    }
    auto size() const -> size_type { return vec.size(); }
    auto size() const -> size_type
    {
        return vec.size();
    }

    vector_view(const decltype(vec) v, const decltype(offset) o)
            : vec(v), offset(o)

M include/viua/assembler/frontend/static_analyser.h => include/viua/assembler/frontend/static_analyser.h +45 -13
@@ 24,6 24,7 @@
#include <optional>
#include <set>
#include <string>

#include <viua/assembler/frontend/parser.h>




@@ 124,8 125,10 @@ class Register_usage_profile {
    auto fresh(Register const) const -> bool;

  public:
    std::map<std::string, viua::bytecode::codec::register_index_type> name_to_index;
    std::map<viua::bytecode::codec::register_index_type, std::string> index_to_name;
    std::map<std::string, viua::bytecode::codec::register_index_type>
        name_to_index;
    std::map<viua::bytecode::codec::register_index_type, std::string>
        index_to_name;

    auto define(Register const r,
                viua::cg::lex::Token const t,


@@ 234,8 237,9 @@ auto assert_type_of_register(Register_usage_profile& register_usage_profile,
        return expected_type;
    }

    auto actual_type =
    auto const original_type =
        register_usage_profile.at(Register(register_index)).second.value_type;
    auto actual_type = original_type;

    auto access_via_pointer_dereference =
        (register_index.as


@@ 263,10 267,6 @@ auto assert_type_of_register(Register_usage_profile& register_usage_profile,
            throw error;
        }

        /*
         * Modify types only if they are defined.
         * Tinkering with UNDEFINEDs will prevent inferencer from kicking in.
         */
        if (actual_type != Value_types::UNDEFINED) {
            actual_type = (actual_type ^ Value_types::POINTER);
        }


@@ 288,18 288,28 @@ auto assert_type_of_register(Register_usage_profile& register_usage_profile,
        return depointerise_type_if_needed(actual_type,
                                           access_via_pointer_dereference);
    }
    if (not(actual_type & expected_type)) {

    auto const type_matches = static_cast<bool>(actual_type & expected_type);
    auto const is_pointer_type =
        static_cast<bool>(original_type & Value_types::POINTER);
    auto const pointerness_matches =
        ((access_via_pointer_dereference and is_pointer_type)
         or ((not access_via_pointer_dereference) and (not is_pointer_type)));
    if ((not type_matches) or (not pointerness_matches)) {
        auto error =
            Traced_syntax_error{}
                .append(Invalid_syntax(
                            register_index.tokens.at(0),
                            "invalid type of value contained in register")
                .append(Invalid_syntax{
                    register_index.tokens.at(0),
                    "invalid type of value contained in register"}
                            .note("expected " + to_string(expected_type)
                                  + ", got " + to_string(actual_type)))
                .append(Invalid_syntax(register_usage_profile.defined_where(
                .append(Invalid_syntax{register_usage_profile.defined_where(
                                           Register(register_index)),
                                       "")
                                       ""}
                            .note("register defined here"));
        // FIXME if a type is first references as a value, and then incorrectly
        // as a pointer the error message does not include the "type inferred
        // here" line
        if (auto r = register_usage_profile.at(Register(register_index)).second;
            r.inferred.first) {
            error.append(Invalid_syntax(r.inferred.second, "")


@@ 501,6 511,12 @@ auto check_op_structat(Register_usage_profile& register_usage_profile,
                       Instruction const& instruction) -> void;
auto check_op_structkeys(Register_usage_profile& register_usage_profile,
                         Instruction const& instruction) -> void;
auto check_op_exception(Register_usage_profile& register_usage_profile,
                        Instruction const& instruction) -> void;
auto check_op_exception_tag(Register_usage_profile& register_usage_profile,
                            Instruction const& instruction) -> void;
auto check_op_exception_value(Register_usage_profile& register_usage_profile,
                              Instruction const& instruction) -> void;
auto check_op_io_read(Register_usage_profile& register_usage_profile,
                      Instruction const& instruction) -> void;
auto check_op_io_write(Register_usage_profile& register_usage_profile,


@@ 527,6 543,22 @@ auto check_register_usage_for_instruction_block_impl(Register_usage_profile&,
                                                     InstructionIndex,
                                                     InstructionIndex) -> void;

struct Safe_result {
    std::optional<viua::cg::lex::Unused_register> unused_register;
    std::optional<viua::cg::lex::Unused_value> unused_value;
    std::optional<viua::cg::lex::Invalid_syntax> invalid_syntax;
    std::optional<viua::cg::lex::Traced_syntax_error> traced_syntax;

    auto ok() const -> bool;
    auto raise_if_any() -> void;
};
auto check_register_usage_for_instruction_block_impl_safe(
    Register_usage_profile&,
    Parsed_source const&,
    Instructions_block const&,
    InstructionIndex,
    InstructionIndex) -> Safe_result;

auto map_names_to_register_indexes(Register_usage_profile&,
                                   Instructions_block const&) -> void;
auto erase_if_direct_access(

M include/viua/assembler/util/pretty_printer.h => include/viua/assembler/util/pretty_printer.h +1 -0
@@ 22,6 22,7 @@

#include <string>
#include <vector>

#include <viua/cg/lex.h>

namespace viua {

M include/viua/assert.h => include/viua/assert.h +3 -1
@@ 22,6 22,7 @@

#include <memory>
#include <string>

#include <viua/exceptions.h>
#include <viua/kernel/frame.h>
#include <viua/types/value.h>


@@ 49,7 50,8 @@ void assert_arity(const Frame* frame, A const&... valid_arities)
    Arity arity = frame->arguments->size();
    if (not any_equal(arity, valid_arities...)) {
        auto ex = std::unique_ptr<viua::types::Exception>{};
        ex.reset(new Arity_exception(arity, {static_cast<Arity>(valid_arities)...}));
        ex.reset(
            new Arity_exception(arity, {static_cast<Arity>(valid_arities)...}));
        throw ex;
    }
}

M include/viua/bytecode/bytetypedef.h => include/viua/bytecode/bytetypedef.h +2 -4
@@ 22,10 22,8 @@

#include <stdint.h>

namespace viua { namespace internals {
namespace types {
namespace viua { namespace internals { namespace types {
using Op_address_type = uint8_t const*;
}  // namespace types
}}  // namespace viua::internals
}}}  // namespace viua::internals::types

#endif

M include/viua/bytecode/codec.h => include/viua/bytecode/codec.h +2 -2
@@ 95,9 95,9 @@ enum class Register_set : uint8_t {

using register_index_type = uint16_t;

using plain_int_type = int32_t;
using plain_int_type   = int32_t;
using plain_float_type = double;
using timeout_type = uint32_t;
using timeout_type     = uint32_t;

using bits_size_type = uint64_t;


M include/viua/bytecode/codec/main.h => include/viua/bytecode/codec/main.h +1 -0
@@ 23,6 23,7 @@
#include <cstdint>
#include <string>
#include <vector>

#include <viua/bytecode/codec.h>
#include <viua/bytecode/opcodes.h>
#include <viua/bytecode/operand_types.h>

M include/viua/bytecode/maps.h => include/viua/bytecode/maps.h +5 -0
@@ 25,6 25,7 @@
#include <set>
#include <string>
#include <vector>

#include <viua/bytecode/opcodes.h>
#include <viua/bytecode/operand_types.h>



@@ 195,6 196,10 @@ std::map<enum OPCODE, std::string> const OP_NAMES = {
    {STRUCTAT, "structat"},
    {STRUCTKEYS, "structkeys"},

    {EXCEPTION, "exception"},
    {EXCEPTION_TAG, "exception_tag"},
    {EXCEPTION_VALUE, "exception_value"},

    {IO_READ, "io_read"},
    {IO_WRITE, "io_write"},
    {IO_CLOSE, "io_close"},

M include/viua/bytecode/opcodes.h => include/viua/bytecode/opcodes.h +16 -3
@@ 333,9 333,9 @@ enum OPCODE : uint8_t {
    FUNCTION,

    // Opcodes related to functions.
    FRAME,  // create new frame (required before param and pamv) for future
            // function call
    CALL,   // call given function with parameters set in parameter register,
    FRAME,     // create new frame (required before param and pamv) for future
               // function call
    CALL,      // call given function with parameters set in parameter register,
    TAILCALL,  // perform a tail call to a function
    DEFER,  // call a function just after the frame it was called in is popped
            // off the stack


@@ 429,6 429,19 @@ enum OPCODE : uint8_t {
     */
    STRUCTKEYS,

    /*
     * Create an exception.
     */
    EXCEPTION,
    /*
     * Obtain the tag of an exception.
     */
    EXCEPTION_TAG,
    /*
     * Obtain the value of an exception.
     */
    EXCEPTION_VALUE,

    IO_READ,
    IO_WRITE,
    IO_CLOSE,

M include/viua/bytecode/operand_types.h => include/viua/bytecode/operand_types.h +3 -1
@@ 23,7 23,7 @@
#include <stdint.h>

enum OperandType : uint8_t {
    OT_INVALID = 0,
    OT_INVALID            = 0,
    OT_REGISTER_INDEX     = 1,  // register index
    OT_REGISTER_REFERENCE = 2,  // register reference (indirect register index)
    OT_REGISTER_INDEX_ANNOTATED = 3,  // register index with an annotation from


@@ 119,6 119,8 @@ enum class Value_types : ValueTypesType {
    IO_REQUEST   = 1 << 16,
    IO_PORT      = 1 << 17,
    IO_PORT_LIKE = (IO_PORT | INTEGER),

    EXCEPTION = 1 << 18,
};
}}  // namespace viua::internals


M include/viua/cg/assembler/assembler.h => include/viua/cg/assembler/assembler.h +1 -0
@@ 26,6 26,7 @@
#include <string>
#include <tuple>
#include <vector>

#include <viua/cg/lex.h>
#include <viua/program.h>


M include/viua/cg/tools.h => include/viua/cg/tools.h +2 -1
@@ 21,8 21,9 @@
#define VIUA_CG_TOOLS_H

#include <cstdint>
#include <viua/bytecode/maps.h>

#include <viua/bytecode/codec.h>
#include <viua/bytecode/maps.h>
#include <viua/cg/lex.h>



M include/viua/exceptions.h => include/viua/exceptions.h +81 -22
@@ 23,6 23,7 @@
#include <sstream>
#include <string>
#include <vector>

#include <viua/bytecode/codec.h>
#include <viua/types/exception.h>
#include <viua/util/exceptions.h>


@@ 30,8 31,12 @@

class Out_of_range_exception : public viua::types::Exception {
  public:
    std::string type() const { return "Out_of_range_exception"; }
    Out_of_range_exception(std::string const& s) : viua::types::Exception(s) {}
    std::string type() const
    {
        return "Out_of_range_exception";
    }
    Out_of_range_exception(std::string const& s) : viua::types::Exception(s)
    {}
};

class Arity_exception : public viua::types::Exception {


@@ 39,7 44,10 @@ class Arity_exception : public viua::types::Exception {
    std::vector<decltype(got_arity)> valid_arities;

  public:
    std::string type() const override { return "Arity_exception"; }
    std::string type() const override
    {
        return "Arity_exception";
    }

    std::string str() const override
    {


@@ 62,12 70,16 @@ class Arity_exception : public viua::types::Exception {
            got_arity, valid_arities);
    }

    std::string what() const override { return str(); }
    std::string what() const override
    {
        return str();
    }

    Arity_exception(decltype(got_arity) a, decltype(valid_arities) v)
            : got_arity(a), valid_arities(v)
    {}
    ~Arity_exception() {}
    ~Arity_exception()
    {}
};

class Type_exception : public viua::types::Exception {


@@ 75,7 87,10 @@ class Type_exception : public viua::types::Exception {
    std::string got;

  public:
    std::string type() const override { return "Type_exception"; }
    std::string type() const override
    {
        return "Type_exception";
    }

    std::string str() const override
    {


@@ 90,18 105,25 @@ class Type_exception : public viua::types::Exception {
            expected, got);
    }

    std::string what() const override { return str(); }
    std::string what() const override
    {
        return str();
    }

    Type_exception(decltype(expected) e, decltype(got) g) : expected(e), got(g)
    {}
    ~Type_exception() {}
    ~Type_exception()
    {}
};

class Unresolved_atom_exception : public viua::types::Exception {
    std::string atom;

  public:
    std::string type() const override { return "Unresolved_atom_exception"; }
    std::string type() const override
    {
        return "Unresolved_atom_exception";
    }

    std::string str() const override
    {


@@ 114,17 136,28 @@ class Unresolved_atom_exception : public viua::types::Exception {
            Unresolved_atom_exception>(atom);
    }

    std::string what() const override { return str(); }
    std::string what() const override
    {
        return str();
    }

    Unresolved_atom_exception(decltype(atom) a) : atom(a) {}
    ~Unresolved_atom_exception() {}
    Unresolved_atom_exception(decltype(atom) a) : atom(a)
    {}
    ~Unresolved_atom_exception()
    {}
};

class Operand_type_exception : public viua::types::Exception {
  public:
    std::string type() const override { return "Operand_type_exception"; }
    std::string type() const override
    {
        return "Operand_type_exception";
    }

    std::string str() const override { return "invalid operand type"; }
    std::string str() const override
    {
        return "invalid operand type";
    }

    std::unique_ptr<Value> copy() const override
    {


@@ 132,37 165,63 @@ class Operand_type_exception : public viua::types::Exception {
            Operand_type_exception>();
    }

    std::string what() const override { return str(); }
    std::string what() const override
    {
        return str();
    }
};

namespace viua { namespace runtime { namespace exceptions {
class Zero_division : public viua::types::Exception {
  public:
    std::string type() const override { return "Zero_division"; }
    std::string type() const override
    {
        return "Zero_division";
    }

    std::string str() const override { return "zero division"; }
    std::string str() const override
    {
        return "zero division";
    }

    std::unique_ptr<Value> copy() const override
    {
        return viua::util::exceptions::make_unique_exception<Zero_division>();
    }

    std::string what() const override { return str(); }
    std::string what() const override
    {
        return str();
    }
};

class Invalid_field_access : public viua::types::Exception {
    std::string const what_field;

  public:
    std::string type() const override { return "Invalid_field_access"; }
    std::string type() const override
    {
        return "Invalid_field_access";
    }

    std::string str() const override { return "invalid field access"; }
    std::string str() const override
    {
        return "invalid field access: '" + what_field + "'";
    }

    std::unique_ptr<Value> copy() const override
    {
        return viua::util::exceptions::make_unique_exception<
            Invalid_field_access>();
            Invalid_field_access>(what_field);
    }

    std::string what() const override { return str(); }
    std::string what() const override
    {
        return str();
    }

    Invalid_field_access(std::string f) : what_field{std::move(f)}
    {}
};
}}}  // namespace viua::runtime::exceptions


M include/viua/front/asm.h => include/viua/front/asm.h +1 -0
@@ 23,6 23,7 @@
#include <map>
#include <string>
#include <vector>

#include <viua/cg/lex.h>
#include <viua/program.h>


M include/viua/front/vm.h => include/viua/front/vm.h +1 -0
@@ 19,6 19,7 @@

#include <string>
#include <vector>

#include <viua/kernel/kernel.h>
#include <viua/loader.h>
#include <viua/support/env.h>

M include/viua/include/module.h => include/viua/include/module.h +1 -1
@@ 23,9 23,9 @@
#include <functional>
#include <string>
#include <vector>

#include <viua/kernel/frame.h>
#include <viua/kernel/registerset.h>
#include <viua/types/object.h>


const auto VIUAPATH = std::vector<std::string>{

M include/viua/kernel/catcher.h => include/viua/kernel/catcher.h +1 -0
@@ 21,6 21,7 @@
#define VIUA_CPU_CATCHER_H

#include <string>

#include <viua/bytecode/bytetypedef.h>

class Catcher {

M include/viua/kernel/frame.h => include/viua/kernel/frame.h +1 -0
@@ 23,6 23,7 @@
#include <memory>
#include <string>
#include <vector>

#include <viua/bytecode/bytetypedef.h>
#include <viua/kernel/registerset.h>
#include <viua/util/memory.h>

M include/viua/kernel/kernel.h => include/viua/kernel/kernel.h +31 -21
@@ 1,5 1,5 @@
/*
 *  Copyright (C) 2015-2019 Marek Marecki
 *  Copyright (C) 2015-2020 Marek Marecki
 *
 *  This file is part of Viua VM.
 *


@@ 20,12 20,13 @@
#ifndef VIUA_CPU_H
#define VIUA_CPU_H

#include <dlfcn.h>

#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <deque>
#include <dlfcn.h>
#include <iostream>
#include <map>
#include <memory>


@@ 39,9 40,11 @@
#include <unordered_set>
#include <utility>
#include <vector>

#include <viua/bytecode/bytetypedef.h>
#include <viua/include/module.h>
#include <viua/process.h>
#include <viua/runtime/imports.h>


namespace viua {


@@ 145,16 148,16 @@ class Kernel {
    std::map<std::string, viua::bytecode::codec::bytecode_size_type>
        block_addresses;

    std::map<std::string, std::pair<std::string, uint8_t*>>
        linked_functions;
    std::map<std::string, std::pair<std::string, uint8_t*>>
        linked_blocks;
    std::map<std::string, std::pair<std::string, uint8_t*>> linked_functions;
    std::map<std::string, std::pair<std::string, uint8_t*>> linked_blocks;
    std::map<std::string,
             std::pair<viua::bytecode::codec::bytecode_size_type,
                       std::unique_ptr<uint8_t[]>>>
        linked_modules;

    int return_code;
    std::map<std::string, std::string> loaded_module_paths;

    int return_code{-1};

    /*
     * The number of running processes. This is needed to calculate the load on


@@ 199,7 202,7 @@ class Kernel {
     *
     */
    // Foreign function call requests are placed here to be executed later.
    std::vector<
    std::queue<
        std::unique_ptr<viua::scheduler::ffi::Foreign_function_call_request>>
        foreign_call_queue;
    std::mutex foreign_call_queue_mutex;


@@ 255,6 258,12 @@ class Kernel {
    std::map<std::tuple<uint64_t, uint64_t>, IO_result> io_results;

    /*
     * PID MANAGEMENT
     */
    viua::process::Pid_emitter pid_sequence;
    mutable std::mutex pid_mutex;

    /*
     * MESSAGE PASSING
     *
     * Why are mailboxes are kept inside the kernel? To remove the need to look


@@ 265,7 274,7 @@ class Kernel {
     * indirection but in this case I think it is justified.
     */
    std::map<viua::process::PID, Mailbox> mailboxes;
    std::mutex mailbox_mutex;
    mutable std::mutex mailbox_mutex;

    /*
     * Only processes that were not disowned have an entry here.


@@ 300,7 309,8 @@ class Kernel {

    Kernel& mapfunction(std::string const&,
                        viua::bytecode::codec::bytecode_size_type);
    Kernel& mapblock(std::string const&, viua::bytecode::codec::bytecode_size_type);
    Kernel& mapblock(std::string const&,
                     viua::bytecode::codec::bytecode_size_type);

    Kernel& register_external_function(std::string const&, ForeignFunction*);
    Kernel& remove_external_function(std::string);


@@ 320,8 330,11 @@ class Kernel {
    auto get_entry_point_of(std::string const&) const
        -> std::pair<viua::internals::types::Op_address_type,
                     viua::internals::types::Op_address_type>;
    auto module_at(uint8_t const* const) const
        -> std::optional<std::pair<std::string, std::string>>;
    auto in_which_function(std::string const, uint64_t const) const
        -> std::optional<std::string>;

    void request_foreign_function_call(Frame*, viua::process::Process*);
    void request_foreign_function_call(std::unique_ptr<Frame>,
                                       viua::process::Process&);



@@ 332,10 345,10 @@ class Kernel {
    auto notify_about_process_death() -> void;
    auto process_count() const -> size_t;

    auto create_mailbox(const viua::process::PID)
        -> size_t;
    auto delete_mailbox(const viua::process::PID)
        -> size_t;
    auto make_pid() -> viua::process::PID;

    auto create_mailbox(const viua::process::PID) -> size_t;
    auto delete_mailbox(const viua::process::PID) -> size_t;

    auto create_result_slot_for(viua::process::PID) -> void;
    auto detach_process(const viua::process::PID) -> void;


@@ 361,12 374,9 @@ class Kernel {
    auto io_result(std::tuple<uint64_t, uint64_t> const)
        -> std::unique_ptr<viua::types::Value>;

    auto static no_of_process_schedulers()
        -> size_t;
    auto static no_of_ffi_schedulers()
        -> size_t;
    auto static no_of_io_schedulers()
        -> size_t;
    auto static no_of_process_schedulers() -> size_t;
    auto static no_of_ffi_schedulers() -> size_t;
    auto static no_of_io_schedulers() -> size_t;
    auto static is_tracing_enabled() -> bool;

    int run();

M include/viua/kernel/registerset.h => include/viua/kernel/registerset.h +43 -30
@@ 22,6 22,7 @@

#include <memory>
#include <vector>

#include <viua/bytecode/codec.h>
#include <viua/types/value.h>



@@ 44,6 45,7 @@ class Register {
    auto empty() const -> bool;

    auto get() -> viua::types::Value*;
    auto get() const -> viua::types::Value const*;
    auto release() -> viua::types::Value*;
    auto give() -> std::unique_ptr<viua::types::Value>;



@@ 57,55 59,66 @@ class Register {

    Register();
    Register(std::unique_ptr<viua::types::Value>);
    Register(Register const&) = delete;
    Register(Register&&);
    ~Register() = default;

    operator bool() const;
    auto operator=(Register &&) -> Register&;
    auto operator=(Register const&) -> Register& = delete;
    auto operator                                =(Register &&) -> Register&;
    auto operator=(decltype(value)&&) -> Register&;
};

class Register_set {
    viua::bytecode::codec::register_index_type registerset_size;
  public:
    using size_type = viua::bytecode::codec::register_index_type;

    size_type registerset_size = 0;
    std::vector<Register> registers;

  public:
    // basic access to registers
    void put(viua::bytecode::codec::register_index_type,
             std::unique_ptr<viua::types::Value>);
    std::unique_ptr<viua::types::Value> pop(
        viua::bytecode::codec::register_index_type);
    void set(viua::bytecode::codec::register_index_type,
             std::unique_ptr<viua::types::Value>);
    viua::types::Value* get(viua::bytecode::codec::register_index_type);
    viua::types::Value* at(viua::bytecode::codec::register_index_type);

    Register* register_at(viua::bytecode::codec::register_index_type);
    auto put(size_type const, std::unique_ptr<viua::types::Value>) -> void;
    auto pop(size_type const) -> std::unique_ptr<viua::types::Value>;
    auto set(size_type const, std::unique_ptr<viua::types::Value>) -> void;
    auto get(size_type const) -> viua::types::Value*;
    auto get(size_type const) const -> viua::types::Value const*;
    auto at(size_type const) -> viua::types::Value*;
    auto at(size_type const) const -> viua::types::Value const*;

    auto register_at(size_type const) -> Register*;

    // register modifications
    void move(viua::bytecode::codec::register_index_type,
              viua::bytecode::codec::register_index_type);
    void swap(viua::bytecode::codec::register_index_type,
              viua::bytecode::codec::register_index_type);
    void empty(viua::bytecode::codec::register_index_type);
    void free(viua::bytecode::codec::register_index_type);
    auto move(size_type const, size_type const) -> void;
    auto swap(size_type const, size_type const) -> void;
    auto empty(size_type const) -> void;
    auto free(size_type const) -> void;

    // mask inspection and manipulation
    void flag(viua::bytecode::codec::register_index_type, mask_type);
    void unflag(viua::bytecode::codec::register_index_type, mask_type);
    void clear(viua::bytecode::codec::register_index_type);
    bool isflagged(viua::bytecode::codec::register_index_type, mask_type);
    void setmask(viua::bytecode::codec::register_index_type, mask_type);
    mask_type getmask(viua::bytecode::codec::register_index_type);

    void drop();
    inline viua::bytecode::codec::register_index_type size()
    auto flag(size_type const, mask_type) -> void;
    auto unflag(size_type const, mask_type) -> void;
    auto clear(size_type const) -> void;
    auto is_flagged(size_type const, mask_type) const -> bool;
    auto set_mask(size_type const, mask_type) -> void;
    auto get_mask(size_type const) const -> mask_type;

    auto drop() -> void;

    inline auto size() const -> size_type
    {
        return registerset_size;
    }
    inline auto empty() const -> bool
    {
        return (size() == 0);
    }

    std::unique_ptr<Register_set> copy();
    auto copy() const -> std::unique_ptr<Register_set>;

    Register_set(viua::bytecode::codec::register_index_type sz);
    Register_set(size_type const);
    Register_set(Register_set const&) = delete;
    Register_set(Register_set&&)      = delete;
    auto operator=(Register_set const&) -> Register_set& = delete;
    auto operator=(Register_set &&) -> Register_set& = delete;
    ~Register_set();
};
}}  // namespace viua::kernel

M include/viua/kernel/tryframe.h => include/viua/kernel/tryframe.h +3 -1
@@ 23,6 23,7 @@
#include <map>
#include <memory>
#include <string>

#include <viua/bytecode/bytetypedef.h>
#include <viua/kernel/catcher.h>
#include <viua/kernel/frame.h>


@@ 41,7 42,8 @@ class Try_frame {
        return return_address;
    }

    Try_frame() : return_address(nullptr), associated_frame(nullptr) {}
    Try_frame() : return_address(nullptr), associated_frame(nullptr)
    {}
};



M include/viua/loader.h => include/viua/loader.h +13 -7
@@ 27,11 27,13 @@
#include <string>
#include <tuple>
#include <vector>

#include <viua/bytecode/codec.h>
#include <viua/machine.h>

using IdToAddressMapping = std::tuple<std::vector<std::string>,
                   std::map<std::string, viua::bytecode::codec::bytecode_size_type>>;
using IdToAddressMapping = std::tuple<
    std::vector<std::string>,
    std::map<std::string, viua::bytecode::codec::bytecode_size_type>>;

template<class T> void readinto(std::ifstream& in, T* object)
{


@@ 55,14 57,16 @@ class Loader {

    std::map<std::string, viua::bytecode::codec::bytecode_size_type>
        function_addresses;
    std::map<std::string, viua::bytecode::codec::bytecode_size_type> function_sizes;
    std::map<std::string, viua::bytecode::codec::bytecode_size_type>
        function_sizes;
    std::vector<std::string> functions;
    std::map<std::string, viua::bytecode::codec::bytecode_size_type>
        block_addresses;
    std::vector<std::string> blocks;

    IdToAddressMapping loadmap(char*,
                               viua::bytecode::codec::bytecode_size_type const&);
    IdToAddressMapping loadmap(
        char*,
        viua::bytecode::codec::bytecode_size_type const&);
    void calculate_function_sizes();

    void load_magic_number(std::ifstream&);


@@ 104,8 108,10 @@ class Loader {

    auto dynamic_imports() const -> std::vector<std::string>;

    Loader(std::string pth) : path(pth), size(0), bytecode(nullptr) {}
    ~Loader() {}
    Loader(std::string pth) : path(pth), size(0), bytecode(nullptr)
    {}
    ~Loader()
    {}
};



M include/viua/pid.h => include/viua/pid.h +59 -10
@@ 1,5 1,5 @@
/*
 *  Copyright (C) 2016 Marek Marecki
 *  Copyright (C) 2016, 2020 Marek Marecki
 *
 *  This file is part of Viua VM.
 *


@@ 26,19 26,68 @@
namespace viua { namespace process {
class Process;

class PID {
    const viua::process::Process* associated_process;
struct PID {
    using pid_type =
        std::tuple<uint64_t  // base:  chosen randomly at VM start
                   ,
                   uint64_t  // big:   increasing sequentially; begins with a
                             // randomly chosen
                             //        highest and lowest 16 bits
                   ,
                   uint32_t  // small: increasing sequentially; begins with a
                             // randomly chosen
                             //        highest 12 and lowest 8 bits
                   ,
                   uint16_t  // n:     increasing sequentially every big N
                             // (randomly chosen at VM
                             //        start from [0; 2^8)); begins with random
                             //        [0; 2^16)
                   ,
                   uint16_t  // m:     increasing sequentially every small M
                             // (randomly chosen at VM
                             //        start); begins with random [0; 2^8)
                   >;

  private:
    pid_type const value;

  public:
    bool operator==(viua::process::PID const&) const;
    bool operator==(const viua::process::Process*) const;
    bool operator<(viua::process::PID const&) const;
    bool operator>(viua::process::PID const&) const;
    auto operator<(PID const&) const -> bool;
    auto operator==(PID const&) const -> bool;
    auto operator!=(PID const&) const -> bool;

    auto get() const -> pid_type;
    auto str(bool const readable = true) const -> std::string;

    PID(pid_type const);
};

class Pid_emitter {
    // 1st field
    uint64_t base = 0;

    auto get() const -> decltype(associated_process);
    auto str() const -> std::string;
    // 2nd field
    uint64_t big_offset = 0;
    uint64_t big        = 0;

    // 3rd field
    uint32_t small_offset = 0;
    uint32_t small        = 0;

    // 4th field
    uint8_t n_modulo  = 1;
    uint16_t n_offset = 0;
    uint16_t n        = 0;

    // 5th field
    uint8_t m_modulo  = 1;
    uint16_t m_offset = 0;
    uint16_t m        = 0;

  public:
    Pid_emitter();

    PID(const viua::process::Process*);
    auto emit() -> PID::pid_type;
};
}}  // namespace viua::process


M include/viua/printutils.h => include/viua/printutils.h +1 -0
@@ 21,6 21,7 @@
#define VIUA_PRINTUTILS

#include <string>

#include <viua/kernel/frame.h>

std::string stringify_function_invocation(const Frame*);

M include/viua/process.h => include/viua/process.h +80 -20
@@ 27,8 27,10 @@
#include <memory>
#include <mutex>
#include <queue>
#include <set>
#include <stack>
#include <string>

#include <viua/bytecode/bytetypedef.h>
#include <viua/bytecode/codec/main.h>
#include <viua/include/module.h>


@@ 43,7 45,8 @@

class Halt_exception : public std::runtime_error {
  public:
    Halt_exception() : std::runtime_error("execution halted") {}
    Halt_exception() : std::runtime_error("execution halted")
    {}
};




@@ 169,7 172,8 @@ class Stack {
    auto register_deferred_calls_from(Frame*) -> void;
    auto register_deferred_calls(bool const = true) -> void;

    auto prepare_frame(viua::bytecode::codec::register_index_type const) -> Frame*;
    auto prepare_frame(viua::bytecode::codec::register_index_type const)
        -> Frame*;
    auto push_prepared_frame() -> void;

    auto adjust_jump_base_for_block(std::string const&)


@@ 183,7 187,7 @@ class Stack {
          viua::kernel::Register_set*,
          viua::scheduler::Process_scheduler*);

    static uint16_t const MAX_STACK_SIZE = 8192;
    constexpr static auto MAX_STACK_SIZE = uint16_t{8192};
};

struct Decoder_adapter {


@@ 198,7 202,9 @@ struct Decoder_adapter {
        if (converted == nullptr) {
            // FIXME don't use the old generic-exception type
            throw std::make_unique<viua::types::Exception>(
                ("fetched invalid type: expected '" + T::type_name
                // FIXME C++20 will make this std::string{...} ctor call
                // obsolete
                ("fetched invalid type: expected '" + std::string{T::type_name}
                 + "' but got '" + value->type() + "'")
                /* "Invalid_type" */
                /* , "expected " + T::type_name + ", got " + value->type() */


@@ 222,7 228,9 @@ struct Decoder_adapter {
        if (converted == nullptr) {
            // FIXME don't use the old generic-exception type
            throw std::make_unique<viua::types::Exception>(
                ("fetched invalid type: expected '" + T::type_name
                // FIXME C++20 will make this std::string{...} ctor call
                // obsolete
                ("fetched invalid type: expected '" + std::string{T::type_name}
                 + "' but got '" + value->type() + "'")
                /* "Invalid_type" */
                /* , "expected " + T::type_name + ", got " + value->type() */


@@ 246,7 254,8 @@ struct Decoder_adapter {
    auto fetch_tagged_register(Op_address_type&,
                               Process&,
                               bool const = false) const
        -> std::pair<viua::bytecode::codec::Register_set, viua::kernel::Register*>;
        -> std::pair<viua::bytecode::codec::Register_set,
                     viua::kernel::Register*>;
    auto fetch_register_index(Op_address_type&) const
        -> viua::bytecode::codec::register_index_type;
    auto fetch_tagged_register_index(Op_address_type&) const


@@ 275,8 284,7 @@ class Process {
     * regarding executed code.
     */
    bool const tracing_enabled;
    auto get_trace_line(uint8_t const*) const
        -> std::string;
    auto get_trace_line(uint8_t const*) const -> std::string;
    auto emit_trace_line(uint8_t const*) const -> void;

    /*


@@ 322,6 330,28 @@ class Process {


    /*
     * This is a set of values that have had a pointer taken and are alive (were
     * not destroyed).
     *
     * Any value allocated for use in Viua VM knows if a pointer has been taken
     * to it; as it is the value itself that creates the pointer (and then
     * notifies the process inside which this happened). This means that a
     * process is aware of the possibility that a pointer to that value exists.
     *
     * When the value is destroyed its pointer is removed from this set. From
     * that moment, pointer liveness checks will fail for any pointer that is
     * pointing to that value.
     *
     * This set MUST only be accessed by one thread at a time to avoid race
     * conditions, but we do not have to guard it with a mutex because a process
     * is only ever manipulated by a single thread (proc scheduler code is
     * responsible for guaranteeing this assumption holds).
     */
    using Pointer_map_type = std::set<viua::types::Value const*>;
    Pointer_map_type live_pointers;


    /*
     * Call stack information.
     *
     * A process may have many suspended stacks (the simplest example: during


@@ 344,6 374,7 @@ class Process {
    Stack* stack;
    std::stack<Stack*> stacks_order;


    /*
     * Messages which the process already has locally. To avoid synchronisation
     * with the kernel on every receive operation, messages are buffered locally


@@ 382,10 413,10 @@ class Process {
    uint16_t process_priority;
    std::mutex process_mtx;

    /*  viua::process::Process identifier.
    /*
     * Process identifier. Used to join processes and send them messages.
     */
    viua::process::PID process_id;
    bool is_hidden;
    viua::process::PID const process_id;

    /*
     * Timeouts for receiving messages, waiting for processes, and waiting for


@@ 422,6 453,7 @@ class Process {
    auto opeq(Op_address_type) -> Op_address_type;

    auto opstring(Op_address_type) -> Op_address_type;
    auto opstreq(Op_address_type) -> Op_address_type;

    auto optext(Op_address_type) -> Op_address_type;
    auto optexteq(Op_address_type) -> Op_address_type;


@@ 542,6 574,8 @@ class Process {
    auto opthrow(Op_address_type) -> Op_address_type;
    auto opleave(Op_address_type) -> Op_address_type;

    auto opimport(Op_address_type) -> Op_address_type;

    auto opatom(Op_address_type) -> Op_address_type;
    auto opatomeq(Op_address_type) -> Op_address_type;



@@ 551,7 585,9 @@ class Process {
    auto opstructat(Op_address_type) -> Op_address_type;
    auto opstructkeys(Op_address_type) -> Op_address_type;

    auto opimport(Op_address_type) -> Op_address_type;
    auto op_exception(Op_address_type) -> Op_address_type;
    auto op_exception_tag(Op_address_type) -> Op_address_type;
    auto op_exception_value(Op_address_type) -> Op_address_type;

    auto op_io_read(Op_address_type) -> Op_address_type;
    auto op_io_write(Op_address_type) -> Op_address_type;


@@ 564,7 600,8 @@ class Process {
    auto tick() -> Op_address_type;

    auto register_at(viua::bytecode::codec::register_index_type,
                     viua::bytecode::codec::Register_set) -> viua::kernel::Register*;
                     viua::bytecode::codec::Register_set)
        -> viua::kernel::Register*;

    bool joinable() const;
    void join();


@@ 587,6 624,7 @@ class Process {
    auto terminated() const -> bool;
    auto get_active_exception() -> viua::types::Value*;
    auto transfer_active_exception() -> std::unique_ptr<viua::types::Value>;
    auto raise(std::unique_ptr<viua::types::Exception>) -> void;
    auto raise(std::unique_ptr<viua::types::Value>) -> void;
    auto handle_active_exception() -> void;



@@ 603,30 641,52 @@ class Process {
    auto start() -> Op_address_type;
    auto execution_at() const -> decltype(Stack::instruction_pointer);

    auto trace() const -> std::vector<Frame*>;
    using Trace_type = std::vector<Frame const*>;
    auto trace() const -> Trace_type;
    auto depth() const -> Trace_type::size_type;

    auto pid() const -> viua::process::PID;
    auto hidden() const -> bool;
    auto hidden(bool) -> void;

    auto empty() const -> bool;

    auto pin(bool const x = true) -> void { is_pinned_to_scheduler = x; }
    auto pinned() const -> bool { return is_pinned_to_scheduler; }
    auto pin(bool const x = true) -> void
    {
        is_pinned_to_scheduler = x;
    }
    auto pinned() const -> bool
    {
        return is_pinned_to_scheduler;
    }

    auto schedule_io(std::unique_ptr<viua::scheduler::io::IO_interaction>)
        -> void;
    auto cancel_io(std::tuple<uint64_t, uint64_t> const) -> void;

    auto get_kernel() const -> viua::kernel::Kernel&;

    auto attach_pointer(viua::types::Value* const, viua::types::Pointer* const)
        -> void;
    auto detach_pointer(viua::types::Value* const, viua::types::Pointer* const)
        -> void;
    auto invalidate_pointers_of(viua::types::Value* const) -> void;
    auto verify_liveness(viua::types::Pointer&) const -> bool;
    auto verify_liveness(viua::types::Pointer const&) const -> bool;

    Process(std::unique_ptr<Frame>,
            viua::process::PID const,
            viua::scheduler::Process_scheduler*,
            viua::process::Process*,
            bool const             = false,
            Decoder_adapter const& = Decoder_adapter{});
    ~Process();

    static viua::bytecode::codec::register_index_type const DEFAULT_REGISTER_SIZE =
        255;
    constexpr static auto DEFAULT_REGISTER_SIZE =
        viua::bytecode::codec::register_index_type{255};

    inline auto current_stack() -> Stack&
    {
        return *stack;
    }
};
}}  // namespace viua::process


M include/viua/program.h => include/viua/program.h +12 -4
@@ 25,6 25,7 @@
#include <string>
#include <tuple>
#include <vector>

#include <viua/bytecode/bytetypedef.h>
#include <viua/bytecode/codec/main.h>
#include <viua/cg/lex.h>


@@ 58,7 59,7 @@ struct timeout_op {
    timeout_op(Integer_operand_type, viua::bytecode::codec::timeout_type = 0);
    timeout_op(viua::bytecode::codec::timeout_type);
};
using byte_op = std::tuple<bool, uint8_t>;
using byte_op  = std::tuple<bool, uint8_t>;
using float_op = std::tuple<bool, float>;

enum JUMPTYPE {


@@ 119,6 120,7 @@ class Program {
    auto opeq(int_op const, int_op const, int_op const) -> Program&;

    auto opstring(int_op const, std::string const) -> Program&;
    auto opstreq(int_op const, int_op const, int_op const) -> Program&;

    auto optext(int_op const, std::string const) -> Program&;
    auto optext(int_op const, int_op const) -> Program&;


@@ 259,6 261,10 @@ class Program {
    auto opstructat(int_op const, int_op const, int_op const) -> Program&;
    auto opstructkeys(int_op const, int_op const) -> Program&;

    auto op_exception(int_op const, int_op const, int_op const) -> Program&;
    auto op_exception_tag(int_op const, int_op const) -> Program&;
    auto op_exception_value(int_op const, int_op const) -> Program&;

    auto op_io_read(int_op const, int_op const, int_op const) -> Program&;
    auto op_io_write(int_op const, int_op const, int_op const) -> Program&;
    auto op_io_close(int_op const, int_op const) -> Program&;


@@ 274,10 280,12 @@ class Program {
     * must know size of the program.
     */
    auto calculate_jumps(
        std::vector<std::tuple<viua::bytecode::codec::bytecode_size_type,
                               viua::bytecode::codec::bytecode_size_type>> const,
        std::vector<
            std::tuple<viua::bytecode::codec::bytecode_size_type,
                       viua::bytecode::codec::bytecode_size_type>> const,
        std::vector<viua::cg::lex::Token> const&) -> Program&;
    auto jumps() const -> std::vector<viua::bytecode::codec::bytecode_size_type>;
    auto jumps() const
        -> std::vector<viua::bytecode::codec::bytecode_size_type>;

    auto bytecode() const -> std::unique_ptr<uint8_t[]>;
    auto fill(std::unique_ptr<uint8_t[]>) -> Program&;

M include/viua/scheduler/ffi.h => include/viua/scheduler/ffi.h +19 -6
@@ 21,8 21,11 @@
#define VIUA_SCHEDULER_FFI_H

#include <condition_variable>
#include <map>
#include <memory>
#include <mutex>
#include <queue>

#include <viua/include/module.h>




@@ 43,10 46,10 @@ class Foreign_function_call_request {
    viua::kernel::Kernel& kernel;

  public:
    std::string function_name() const;
    void call(ForeignFunction*);
    void raise(std::unique_ptr<viua::types::Value>);
    void wakeup();
    auto function_name() const -> std::string;
    auto call(ForeignFunction*) -> void;
    auto raise(std::unique_ptr<viua::types::Value>) -> void;
    auto wakeup() -> void;

    Foreign_function_call_request(Frame* fr,
                                  viua::process::Process* cp,


@@ 58,11 61,21 @@ class Foreign_function_call_request {
                                  viua::kernel::Kernel& c)
            : frame{std::move(fr)}, caller_process{cp}, kernel{c}
    {}
    ~Foreign_function_call_request() {}

    Foreign_function_call_request(Foreign_function_call_request const&) =
        delete;
    auto operator=(Foreign_function_call_request const&)
        -> Foreign_function_call_request& = delete;

    Foreign_function_call_request(Foreign_function_call_request&&) = delete;
    auto operator                         =(Foreign_function_call_request &&)
        -> Foreign_function_call_request& = delete;

    ~Foreign_function_call_request() = default;
};

void ff_call_processor(
    std::vector<std::unique_ptr<Foreign_function_call_request>>* requests,
    std::queue<std::unique_ptr<Foreign_function_call_request>>* requests,
    std::map<std::string, ForeignFunction*>* foreign_functions,
    std::mutex* ff_map_mtx,
    std::mutex* mtx,

M include/viua/scheduler/io.h => include/viua/scheduler/io.h +1 -0
@@ 24,6 24,7 @@
#include <deque>
#include <memory>
#include <mutex>

#include <viua/scheduler/io/interactions.h>



M include/viua/scheduler/io/interactions.h => include/viua/scheduler/io/interactions.h +36 -9
@@ 101,7 101,10 @@ struct IO_interaction {
    virtual auto interact() -> Interaction_result = 0;

    auto id() const -> id_type;
    virtual auto fd() const -> std::optional<fd_type> { return std::nullopt; }
    virtual auto fd() const -> std::optional<fd_type>
    {
        return std::nullopt;
    }
    virtual auto kind() const -> IO_kind = 0;

    auto cancel() -> void;


@@ 119,8 122,14 @@ struct IO_interaction {
struct IO_empty_interaction : public IO_interaction {
    auto interact() -> Interaction_result override;

    std::optional<fd_type> fd() const override { return std::nullopt; }
    IO_kind kind() const override { return IO_kind::Output; }
    std::optional<fd_type> fd() const override
    {
        return std::nullopt;
    }
    IO_kind kind() const override
    {
        return IO_kind::Output;
    }

    using IO_interaction::IO_interaction;
};


@@ 130,8 139,14 @@ struct IO_read_interaction : public IO_interaction {

    auto interact() -> Interaction_result override;

    std::optional<fd_type> fd() const override { return file_descriptor; }
    IO_kind kind() const override { return IO_kind::Input; }
    std::optional<fd_type> fd() const override
    {
        return file_descriptor;
    }
    IO_kind kind() const override
    {
        return IO_kind::Input;
    }

    IO_read_interaction(id_type const, int const, size_t const);
};


@@ 141,8 156,14 @@ struct IO_write_interaction : public IO_interaction {

    auto interact() -> Interaction_result override;

    std::optional<fd_type> fd() const override { return file_descriptor; }
    IO_kind kind() const override { return IO_kind::Output; }
    std::optional<fd_type> fd() const override
    {
        return file_descriptor;
    }
    IO_kind kind() const override
    {
        return IO_kind::Output;
    }

    IO_write_interaction(id_type const, int const, std::string);
};


@@ 151,8 172,14 @@ struct IO_close_interaction : public IO_interaction {

    auto interact() -> Interaction_result override;

    std::optional<fd_type> fd() const override { return file_descriptor; }
    IO_kind kind() const override { return IO_kind::Close; }
    std::optional<fd_type> fd() const override
    {
        return file_descriptor;
    }
    IO_kind kind() const override
    {
        return IO_kind::Close;
    }

    IO_close_interaction(id_type const, int const);
};

M include/viua/scheduler/process.h => include/viua/scheduler/process.h +5 -1
@@ 27,6 27,7 @@
#include <queue>
#include <thread>
#include <vector>

#include <viua/kernel/frame.h>
#include <viua/pid.h>
#include <viua/scheduler/io/interactions.h>


@@ 198,7 199,10 @@ class Process_scheduler {
    auto join() -> void;
    auto exit() const -> int;

    auto kernel() const -> viua::kernel::Kernel& { return attached_kernel; }
    auto kernel() const -> viua::kernel::Kernel&
    {
        return attached_kernel;
    }

    auto schedule_io(std::unique_ptr<viua::scheduler::io::IO_interaction>)
        -> void;

M include/viua/support/env.h => include/viua/support/env.h +2 -1
@@ 20,8 20,9 @@
#ifndef VIUA_SUPPORT_ENV_H
#define VIUA_SUPPORT_ENV_H

#include <string>
#include <sys/stat.h>

#include <string>
#include <vector>

namespace viua { namespace support { namespace env {

M include/viua/tooling/errors/compile_time/errors.h => include/viua/tooling/errors/compile_time/errors.h +1 -0
@@ 22,6 22,7 @@

#include <memory>
#include <string>

#include <viua/tooling/errors/compile_time.h>
#include <viua/tooling/libs/lexer/tokenise.h>


M include/viua/tooling/libs/lexer/normaliser.h => include/viua/tooling/libs/lexer/normaliser.h +1 -0
@@ 21,6 21,7 @@
#define VIUA_TOOLING_LIBS_LEXER_NORMALISER_H

#include <vector>

#include <viua/tooling/libs/lexer/tokenise.h>

namespace viua { namespace tooling { namespace libs { namespace lexer {

M include/viua/tooling/libs/parser/parser.h => include/viua/tooling/libs/parser/parser.h +2 -1
@@ 23,8 23,9 @@
#include <memory>
#include <string>
#include <vector>
#include <viua/bytecode/codec.h>

#include <viua/bytecode/bytetypedef.h>
#include <viua/bytecode/codec.h>
#include <viua/bytecode/maps.h>
#include <viua/bytecode/operand_types.h>
#include <viua/tooling/libs/lexer/tokenise.h>

M include/viua/tooling/libs/static_analyser/static_analyser.h => include/viua/tooling/libs/static_analyser/static_analyser.h +4 -1
@@ 21,6 21,8 @@
#define VIUA_TOOLING_LIBS_STATIC_ANALYSER_H

#include <set>
#include <optional>

#include <viua/tooling/libs/parser/parser.h>

namespace viua {


@@ 201,7 203,8 @@ class IO_request : public Value {
}  // namespace values

class Function_state {
    viua::bytecode::codec::register_index_type const local_registers_allocated = 0;
    viua::bytecode::codec::register_index_type const local_registers_allocated =
        0;
    std::vector<viua::tooling::libs::lexer::Token>
        local_registers_allocated_where;


M include/viua/types/atom.h => include/viua/types/atom.h +1 -1
@@ 28,7 28,7 @@ class Atom : public Value {
    std::string const value;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Atom";

    virtual std::string type() const override;
    virtual bool boolean() const override;

M include/viua/types/bits.h => include/viua/types/bits.h +3 -2
@@ 24,6 24,7 @@
#include <sstream>
#include <string>
#include <vector>

#include <viua/types/value.h>




@@ 80,11 81,11 @@ class Bits : public viua::types::Value {
    auto operator>(Bits const&) const -> bool;
    auto operator>=(Bits const&) const -> bool;

    auto operator&(Bits const&)const -> std::unique_ptr<Bits>;
    auto operator&(Bits const&) const -> std::unique_ptr<Bits>;
    auto operator|(Bits const&) const -> std::unique_ptr<Bits>;
    auto operator^(Bits const&) const -> std::unique_ptr<Bits>;

    static std::string const type_name;
    constexpr static auto type_name = "Bits";

    std::string type() const override;
    std::string str() const override;

M include/viua/types/boolean.h => include/viua/types/boolean.h +7 -1
@@ 20,8 20,10 @@
#ifndef VIUA_TYPES_BOOLEAN_H
#define VIUA_TYPES_BOOLEAN_H

#include <memory>
#include <sstream>
#include <string>

#include <viua/types/value.h>




@@ 34,7 36,7 @@ class Boolean : public viua::types::Value {
    bool b;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Boolean";

    auto type() const -> std::string override;
    auto str() const -> std::string override;


@@ 45,6 47,10 @@ class Boolean : public viua::types::Value {
    auto copy() const -> std::unique_ptr<Value> override;

    Boolean(bool const v = false);

    static auto make(bool const) -> std::unique_ptr<Boolean>;
    static auto make_true() -> std::unique_ptr<Boolean>;
    static auto make_false() -> std::unique_ptr<Boolean>;
};
}}  // namespace viua::types


M include/viua/types/closure.h => include/viua/types/closure.h +2 -1
@@ 22,6 22,7 @@

#include <memory>
#include <string>

#include <viua/bytecode/bytetypedef.h>
#include <viua/kernel/registerset.h>
#include <viua/types/function.h>


@@ 32,7 33,7 @@ class Closure : public Function {
    std::unique_ptr<viua::kernel::Register_set> local_register_set;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Closure";

    auto type() const -> std::string override;
    auto str() const -> std::string override;

M include/viua/types/exception.h => include/viua/types/exception.h +47 -13
@@ 1,5 1,5 @@
/*
 *  Copyright (C) 2015, 2016, 2017 Marek Marecki
 *  Copyright (C) 2015, 2016, 2017, 2020 Marek Marecki
 *
 *  This file is part of Viua VM.
 *


@@ 20,25 20,54 @@
#ifndef VIUA_TYPES_EXCEPTION_H
#define VIUA_TYPES_EXCEPTION_H

#include <cstdint>
#include <string>
#include <vector>

#include <viua/bytecode/bytetypedef.h>
#include <viua/support/string.h>
#include <viua/types/value.h>


namespace viua { namespace types {
class Exception : public Value {
    /** Exception type.
struct Exception : public Value {
    /*
     * Tag is the value that is used to catch the exception in catch blocks. For
     * example, if the exception has tag 'Foo' it can be caught by the following
     * block:
     *
     *  Thrown when irrecoverable conditions are encountered
     *  during program execution.
     *      catch "Foo" handle_foo
     */
    struct Tag {
        std::string tag;

        Tag(std::string t) : tag{std::move(t)}
        {}
    };
    std::string const tag{"Exception"};

    /*
     * Either of these may be specified, but not both at the same time.
     * The `description` string is just a placeholder for Text-typed values to
     * make it easier to throw exceptions from C++.
     */
  protected:
    std::string cause;
    std::string detailed_type;
    std::string const description{""};
    std::unique_ptr<Value> value{nullptr};

  public:
    static std::string const type_name;
    struct Throw_point {
        uint64_t const jump_base{0};
        uint64_t const offset{0};
        std::string const name{};

        inline Throw_point(uint64_t const j, uint64_t const o)
                : jump_base{j}, offset{o}
        {}
        inline Throw_point(std::string n) : name{std::move(n)}
        {}
    };
    std::vector<Throw_point> throw_points;

    constexpr static auto type_name = "Exception";

    std::string type() const override;
    std::string str() const override;


@@ 47,11 76,16 @@ class Exception : public Value {

    std::unique_ptr<Value> copy() const override;

    virtual std::string what() const;
    virtual std::string etype() const;
    virtual auto what() const -> std::string;

    virtual auto add_throw_point(Throw_point const) -> void;

    Exception(Tag);
    Exception(std::string s = "");
    Exception(std::string ts, std::string cs);
    Exception(std::unique_ptr<Value>);
    Exception(Tag, std::string);
    Exception(Tag, std::unique_ptr<Value>);
    Exception(std::vector<Throw_point>, Tag);
};
}}  // namespace viua::types


M include/viua/types/float.h => include/viua/types/float.h +3 -2
@@ 23,6 23,7 @@
#include <ios>
#include <sstream>
#include <string>

#include <viua/types/number.h>




@@ 38,7 39,7 @@ class Float : public viua::types::numeric::Number {
    underlying_type number;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Float";

    std::string type() const override;
    std::string str() const override;


@@ 53,7 54,7 @@ class Float : public viua::types::numeric::Number {

    auto operator+(Number const&) const -> std::unique_ptr<Number> override;
    auto operator-(Number const&) const -> std::unique_ptr<Number> override;
    auto operator*(Number const&)const -> std::unique_ptr<Number> override;
    auto operator*(Number const&) const -> std::unique_ptr<Number> override;
    auto operator/(Number const&) const -> std::unique_ptr<Number> override;

    auto operator<(Number const&) const -> std::unique_ptr<Boolean> override;

M include/viua/types/function.h => include/viua/types/function.h +2 -1
@@ 21,6 21,7 @@
#define VIUA_TYPE_FUNCTION_H

#include <string>

#include <viua/bytecode/bytetypedef.h>
#include <viua/kernel/registerset.h>
#include <viua/types/value.h>


@@ 29,7 30,7 @@
namespace viua { namespace types {
class Function : public Value {
  public:
    static std::string const type_name;
    constexpr static auto type_name = "Function";

    std::string function_name;


M include/viua/types/integer.h => include/viua/types/integer.h +5 -3
@@ 22,6 22,7 @@

#include <sstream>
#include <string>

#include <viua/types/number.h>




@@ 37,7 38,7 @@ class Integer : public viua::types::numeric::Number {
    underlying_type number;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Integer";

    std::string type() const override;
    std::string str() const override;


@@ 56,7 57,7 @@ class Integer : public viua::types::numeric::Number {

    auto operator+(Number const&) const -> std::unique_ptr<Number> override;
    auto operator-(Number const&) const -> std::unique_ptr<Number> override;
    auto operator*(Number const&)const -> std::unique_ptr<Number> override;
    auto operator*(Number const&) const -> std::unique_ptr<Number> override;
    auto operator/(Number const&) const -> std::unique_ptr<Number> override;

    auto operator<(Number const&) const -> std::unique_ptr<Boolean> override;


@@ 65,7 66,8 @@ class Integer : public viua::types::numeric::Number {
    auto operator>=(Number const&) const -> std::unique_ptr<Boolean> override;
    auto operator==(Number const&) const -> std::unique_ptr<Boolean> override;

    Integer(decltype(number) n = 0) : number(n) {}
    Integer(decltype(number) n = 0) : number(n)
    {}
};
}}  // namespace viua::types


M include/viua/types/io.h => include/viua/types/io.h +8 -4
@@ 21,6 21,7 @@
#define VIUA_TYPES_IO_H

#include <string>

#include <viua/kernel/frame.h>
#include <viua/kernel/registerset.h>
#include <viua/process.h>


@@ 38,14 39,17 @@ class IO_request : public Value {
    viua::kernel::Kernel* const kernel;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "IO_request";

    std::string type() const override;
    std::string str() const override;
    std::string repr() const override;
    bool boolean() const override;

    auto id() const -> interaction_id_type { return interaction_id; }
    auto id() const -> interaction_id_type
    {
        return interaction_id;
    }

    std::unique_ptr<Value> copy() const override;



@@ 61,7 65,7 @@ class IO_port : public Value {
    counter_type counter = 0;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "IO_port";

    std::string type() const override;
    std::string str() const override;


@@ 99,7 103,7 @@ class IO_fd : public IO_port {
    Ownership const ownership;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "IO_fd";

    std::string type() const override;
    std::string str() const override;

M include/viua/types/number.h => include/viua/types/number.h +3 -2
@@ 23,6 23,7 @@
#include <cstdint>
#include <sstream>
#include <string>

#include <viua/types/boolean.h>
#include <viua/types/value.h>



@@ 40,7 41,7 @@ class Number : public Value {
     *  Otherwise, they will not be usable by arithmetic instructions.
     */
  public:
    static std::string const type_name;
    constexpr static auto type_name = "Number";

    std::string type() const override;
    std::string str() const override = 0;


@@ 53,7 54,7 @@ class Number : public Value {

    virtual auto operator+(Number const&) const -> std::unique_ptr<Number> = 0;
    virtual auto operator-(Number const&) const -> std::unique_ptr<Number> = 0;
    virtual auto operator*(Number const&)const -> std::unique_ptr<Number>  = 0;
    virtual auto operator*(Number const&) const -> std::unique_ptr<Number> = 0;
    virtual auto operator/(Number const&) const -> std::unique_ptr<Number> = 0;

    virtual auto operator<(Number const&) const -> std::unique_ptr<Boolean> = 0;

D include/viua/types/object.h => include/viua/types/object.h +0 -61
@@ 1,61 0,0 @@
/*
 *  Copyright (C) 2015, 2016, 2017 Marek Marecki
 *
 *  This file is part of Viua VM.
 *
 *  Viua VM is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Viua VM is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Viua VM.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef VIUA_TYPES_OBJECT_H
#define VIUA_TYPES_OBJECT_H

#include <map>
#include <viua/kernel/frame.h>
#include <viua/kernel/registerset.h>
#include <viua/types/value.h>


namespace viua { namespace types {
class Object : public Value {
    /** A generic object class.
     *
     *  This type is used internally inside the VM.
     */
  private:
    std::string object_type_name;
    std::map<std::string, std::unique_ptr<Value>> attributes;

  public:
    static std::string const type_name;

    std::string type() const override;
    bool boolean() const override;

    std::string str() const override;

    void insert(std::string const& key, std::unique_ptr<Value> value);
    std::unique_ptr<Value> remove(std::string const& key);

    void set(std::string const&, std::unique_ptr<Value>);
    inline Value* at(std::string const& s) { return attributes.at(s).get(); }

    virtual std::unique_ptr<Value> copy() const override;

    Object(std::string const& tn);
    virtual ~Object();
};
}}  // namespace viua::types


#endif

M include/viua/types/pointer.h => include/viua/types/pointer.h +34 -18
@@ 21,6 21,7 @@
#define VIUA_TYPES_POINTER_H

#include <vector>

#include <viua/kernel/frame.h>
#include <viua/types/value.h>



@@ 32,8 33,7 @@ class Kernel;

namespace types {
class Pointer : public Value {
    Value* points_to;
    bool valid;
    Value* points_to = nullptr;
    /*
     *  Pointer of origin is a parallelism-safety token.
     *  Viua asserts that pointers can be dereferenced only


@@ 45,30 45,46 @@ class Pointer : public Value {
     *  pointer should be illegal by definition (even if the access
     *  could be made safe).
     */
    viua::process::Process const* process_of_origin;
    viua::process::PID const origin;

    void attach();
    void detach();

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Pointer";

    void invalidate(Value* t);
    bool expired();
    auto authenticate(viua::process::Process const*) -> void;
    void reset(Value* t);
    Value* to(viua::process::Process const*);
    /*
     * Check if the pointer is expired, and set its state appropriately. Return
     * the new state.
     */
    auto expired(viua::process::Process const&) -> bool;

    /*
     * Authenticate the pointer for use in a process. This causes the pointer to
     * become invalid if it is used outside of its process of origin.
     */
    auto authenticate(viua::process::PID const pid) -> void;

    /*
     * Guarded (via to() function) and unguarded (via of() function) access to
     * the pointee.
     *
     * The to() function requires a process that the value would be used in, and
     * may set the pointer's state to expired if it's not the pointer's process
     * of origin.
     */
    auto to(viua::process::Process const&) -> Value*;
    auto of() const -> Value*;

    std::string str() const override;
    auto str() const -> std::string override;

    std::string type() const override;
    bool boolean() const override;
    auto type() const -> std::string override;
    auto boolean() const -> bool override;

    std::unique_ptr<Value> copy() const override;
    auto copy() const -> std::unique_ptr<Value> override;
    auto expire() -> void override;

    Pointer(viua::process::Process const*);
    Pointer(Value* t, viua::process::Process const*);
    virtual ~Pointer();
    Pointer(viua::process::PID const);
    Pointer(Value* t, viua::process::PID const);
    ~Pointer() override;
};
}  // namespace types
}  // namespace viua

M include/viua/types/process.h => include/viua/types/process.h +2 -1
@@ 22,6 22,7 @@

#include <memory>
#include <string>

#include <viua/kernel/frame.h>
#include <viua/kernel/registerset.h>
#include <viua/process.h>


@@ 43,7 44,7 @@ class Process : public Value {
    viua::process::PID saved_pid;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Process";

    /*
     * For use by the VM and user code.

M include/viua/types/reference.h => include/viua/types/reference.h +2 -1
@@ 24,6 24,7 @@
#include <memory>
#include <string>
#include <vector>

#include <viua/types/value.h>

namespace viua { namespace types {


@@ 33,7 34,7 @@ class Reference : public Value {
    uint64_t* counter;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Reference";

    std::string type() const override;
    std::string str() const override;

M include/viua/types/string.h => include/viua/types/string.h +8 -51
@@ 1,5 1,5 @@
/*
 *  Copyright (C) 2015, 2016, 2017 Marek Marecki
 *  Copyright (C) 2015-2017, 2020 Marek Marecki
 *
 *  This file is part of Viua VM.
 *


@@ 20,7 20,9 @@
#ifndef VIUA_TYPES_STRING_H
#define VIUA_TYPES_STRING_H

#include <memory>
#include <string>

#include <viua/kernel/frame.h>
#include <viua/kernel/registerset.h>
#include <viua/support/string.h>


@@ 50,7 52,7 @@ class String : public Value {
    std::string svalue;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "String";

    std::string type() const override;
    std::string str() const override;


@@ 59,63 61,18 @@ class String : public Value {

    std::unique_ptr<Value> copy() const override;

    std::string& value();

    Integer* size();
    String* sub(int64_t b = 0, int64_t e = -1);
    String* add(String*);
    String* join(Vector*);

    virtual void stringify(Frame*,
                           viua::kernel::Register_set*,
                           viua::kernel::Register_set*,
                           viua::process::Process*,
                           viua::kernel::Kernel*);
    virtual void represent(Frame*,
                           viua::kernel::Register_set*,
                           viua::kernel::Register_set*,
                           viua::process::Process*,
                           viua::kernel::Kernel*);

    virtual void startswith(Frame*,
                            viua::kernel::Register_set*,
                            viua::kernel::Register_set*,
                            viua::process::Process*,
                            viua::kernel::Kernel*);
    virtual void endswith(Frame*,
                          viua::kernel::Register_set*,
                          viua::kernel::Register_set*,
                          viua::process::Process*,
                          viua::kernel::Kernel*);
    auto operator==(String const&) const -> bool;

    auto value() const -> std::string const&;

    virtual void format(Frame*,
                        viua::kernel::Register_set*,
                        viua::kernel::Register_set*,
                        viua::process::Process*,
                        viua::kernel::Kernel*);
    virtual void substr(Frame*,
                        viua::kernel::Register_set*,
                        viua::kernel::Register_set*,
                        viua::process::Process*,
                        viua::kernel::Kernel*);
    virtual void concatenate(Frame*,
                             viua::kernel::Register_set*,
                             viua::kernel::Register_set*,
                             viua::process::Process*,
                             viua::kernel::Kernel*);
    virtual void join(Frame*,
                      viua::kernel::Register_set*,
                      viua::kernel::Register_set*,
                      viua::process::Process*,
                      viua::kernel::Kernel*);

    virtual void size(Frame*,
                      viua::kernel::Register_set*,
                      viua::kernel::Register_set*,
                      viua::process::Process*,
                      viua::kernel::Kernel*);

    String(std::string s = "");
    static auto make(std::string = "") -> std::unique_ptr<String>;
};
}}  // namespace viua::types


M include/viua/types/struct.h => include/viua/types/struct.h +4 -2
@@ 23,6 23,7 @@
#include <map>
#include <string>
#include <vector>

#include <viua/types/value.h>




@@ 36,7 37,7 @@ class Struct : public Value {
    std::map<std::string, std::unique_ptr<Value>> attributes;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Struct";

    auto type() const -> std::string override;
    auto boolean() const -> bool override;


@@ 52,8 53,9 @@ class Struct : public Value {
    virtual auto keys() const -> std::vector<std::string>;

    auto copy() const -> std::unique_ptr<Value> override;
    auto expire() -> void override;

    ~Struct() override = default;
    ~Struct() override;
};
}}  // namespace viua::types


M include/viua/types/text.h => include/viua/types/text.h +7 -2
@@ 22,6 22,7 @@

#include <string>
#include <vector>

#include <viua/kernel/frame.h>
#include <viua/kernel/registerset.h>
#include <viua/support/string.h>


@@ 49,11 50,12 @@ class Text : public Value {

  private:
    std::vector<Character> text;
    std::string text_str;

    auto parse(std::string) -> decltype(text);

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Text";

    std::string type() const override;
    std::string str() const override;


@@ 74,10 76,13 @@ class Text : public Value {
    auto common_prefix(Text const&) const -> size_type;
    auto common_suffix(Text const&) const -> size_type;

    auto data() const -> std::string const&;

    Text(std::vector<Character>);
    Text(std::string);
    Text(Text&&);
    ~Text() {}
    ~Text()
    {}
};
}}  // namespace viua::types


M include/viua/types/value.h => include/viua/types/value.h +26 -12
@@ 21,9 21,10 @@
#define VIUA_TYPES_VALUE_H

#include <memory>
#include <sstream>
#include <set>
#include <string>
#include <vector>

#include <viua/pid.h>


namespace viua {


@@ 35,23 36,36 @@ namespace types {
class Pointer;

class Value {
    friend class Pointer;
    std::vector<Pointer*> pointers;
    class viua::process::Process* pointered = nullptr;

  public:
    /** Basic interface of a Value.
    /*
     * Basic interface of a Value.
     *
     *  Derived objects are expected to override this methods, but in case they
     * Derived types are expected to override these methods. In case they do
     * not, Value provides safe defaults.
     * not
     * do not Value provides safe defaults.
     */
    virtual std::string type() const;
    virtual std::string str() const;
    virtual std::string repr() const;
    virtual bool boolean() const;
    virtual auto type() const -> std::string;
    virtual auto str() const -> std::string;
    virtual auto repr() const -> std::string;
    virtual auto boolean() const -> bool;

    virtual std::unique_ptr<Pointer> pointer(const viua::process::Process*);
    /*
     * Called before a value is sent to another process. For types that should
     * not be usable outside of their original process it should set the value
     * to some sane, invalid state; if such a state is impossible to construct
     * the function should throw an exception.
     *
     * This is currently only useful for pointers (as they are the only value
     * that SHOULD NOT be exchanged by processes).
     */
    virtual auto expire() -> void;
    virtual auto pointer(viua::process::Process* const)
        -> std::unique_ptr<Pointer>;

    virtual std::unique_ptr<Value> copy() const = 0;
    virtual auto copy() const -> std::unique_ptr<Value> = 0;

    Value() = default;
    virtual ~Value();

M include/viua/types/vector.h => include/viua/types/vector.h +4 -1
@@ 22,6 22,7 @@

#include <string>
#include <vector>

#include <viua/types/value.h>




@@ 32,7 33,7 @@ class Vector : public Value {
    std::vector<std::unique_ptr<Value>> internal_object;

  public:
    static std::string const type_name;
    constexpr static auto type_name = "Vector";

    std::string type() const override;
    std::string str() const override;


@@ 48,6 49,8 @@ class Vector : public Value {
    Value* at(long int);
    int len();

    auto expire() -> void override;

    Vector();
    Vector(const std::vector<Value*>& v);
    ~Vector();

M include/viua/util/exceptions.h => include/viua/util/exceptions.h +1 -0
@@ 2,6 2,7 @@
#define VIUA_UTIL_EXCEPTIONS_H

#include <memory>

#include <viua/types/exception.h>

namespace viua { namespace util { namespace exceptions {

M include/viua/util/memory.h => include/viua/util/memory.h +34 -8
@@ 29,8 29,8 @@ template<typename T>
using dumb_ptr = T*;  // FIXME; use std::experimental::observer_ptr

template<class T> class maybe_unique_ptr {
    bool owns_pointer;
    T* pointer;
    bool owns_pointer = true;
    T* pointer        = nullptr;

    auto delete_if_owned() -> void
    {


@@ 67,16 67,40 @@ template<class T> class maybe_unique_ptr {
        return *this;
    }

    auto get() -> T* { return pointer; }
    auto get() -> T*
    {
        return pointer;
    }
    auto get() const -> T const*
    {
        return pointer;
    }

    auto owns() const -> bool { return owns_pointer; }
    auto owns() const -> bool
    {
        return owns_pointer;
    }

    auto operator-> () -> T* { return pointer; }
    auto operator->() -> T*
    {
        return pointer;
    }
    auto operator->() const -> T const*
    {
        return pointer;
    }

    maybe_unique_ptr(T* ptr = nullptr, bool own = true)
            : owns_pointer(own), pointer(ptr)
    {}
    ~maybe_unique_ptr() { delete_if_owned(); }
    maybe_unique_ptr(maybe_unique_ptr<T> const&) = delete;
    maybe_unique_ptr(maybe_unique_ptr<T>&&)      = delete;
    auto operator=(maybe_unique_ptr<T> const&) -> maybe_unique_ptr<T>& = delete;
    auto operator=(maybe_unique_ptr<T> &&) -> maybe_unique_ptr<T>& = delete;
    ~maybe_unique_ptr()
    {
        delete_if_owned();
    }
};

template<class To, class From> auto load_aligned(const From* source) -> To


@@ 90,7 114,8 @@ template<class To> class aligned_write_impl {
    To* target;

  public:
    aligned_write_impl(To* t) : target(t) {}
    aligned_write_impl(To* t) : target(t)
    {}

    template<class From>
    auto operator=(const From source) -> aligned_write_impl&


@@ 118,7 143,8 @@ template<class To> class aligned_read_impl {
    To& target;

  public:
    aligned_read_impl(To& t) : target(t) {}
    aligned_read_impl(To& t) : target(t)
    {}

    template<class From>
    auto operator=(const From* source) -> aligned_read_impl&

M include/viua/util/range.h => include/viua/util/range.h +8 -2
@@ 35,8 35,14 @@ template<typename T> class Range {
        std::iota(v.begin(), v.end(), T{0});
    }

    auto begin() const -> decltype(v.begin()) { return v.begin(); }
    auto end() const -> decltype(v.end()) { return v.end(); }
    auto begin() const -> decltype(v.begin())
    {
        return v.begin();
    }
    auto end() const -> decltype(v.end())
    {
        return v.end();
    }
};
}}  // namespace viua::util


M include/viua/util/string/ops.h => include/viua/util/string/ops.h +1 -0
@@ 26,6 26,7 @@
namespace viua { namespace util { namespace string { namespace ops {
auto extract(std::string const&) -> std::string;
auto strencode(std::string const&) -> std::string;
auto strdecode(std::string const) -> std::string;
auto quoted(std::string const&) -> std::string;

using LevenshteinDistance = std::string::size_type;

M include/viua/util/vector_view.h => include/viua/util/vector_view.h +12 -3
@@ 45,8 45,14 @@ template<typename T> class vector_view {
    }

  public:
    auto at(size_type const i) const -> T const& { return vec.at(offset + i); }
    auto size() const -> size_type { return (vec.size() - offset); }
    auto at(size_type const i) const -> T const&
    {
        return vec.at(offset + i);
    }
    auto size() const -> size_type
    {
        return (vec.size() - offset);
    }

    auto advance(size_type const n) const -> vector_view<T>
    {


@@ 57,7 63,10 @@ template<typename T> class vector_view {
    {
        return vec.begin() + static_cast<difference_type>(offset);
    }
    auto end() const -> decltype(vec.end()) { return vec.end(); }
    auto end() const -> decltype(vec.end())
    {
        return vec.end();
    }

    vector_view(container_type const& v, size_type const o) : vec{v}, offset{o}
    {

M include/viua/version.h => include/viua/version.h +1 -1
@@ 34,6 34,6 @@
#define VIUA_VERSION_H

constexpr auto VERSION = "0.10.0";
constexpr auto MICRO   = "11";
constexpr auto MICRO   = "140";

#endif

M sample/asm/external/throwing.asm => sample/asm/external/throwing.asm +3 -3
@@ 34,9 34,9 @@

    move (.name: %iota death_message) local %0 parameters

    .name: %iota exception
    structremove %exception local %death_message local (atom %exception local 'exception') local
    print %exception local
    .name: %iota ex
    structremove %ex local %death_message local (atom %ex local 'exception') local
    print %ex local

    return
.end

M sample/asm/watchdog/already_spawned.asm => sample/asm/watchdog/already_spawned.asm +3 -3
@@ 22,8 22,8 @@

    move (.name: %iota death_message) local %0 parameters

    .name: %iota exception
    structremove %exception %1 (atom %exception 'exception')
    .name: %iota ex
    structremove %ex %1 (atom %ex 'exception')

    .name: %iota aborted_function
    structremove %aborted_function %1 (atom %aborted_function 'function')


@@ 31,7 31,7 @@
    echo (string (.name: %iota message) local "process spawned with <") local
    echo %aborted_function local
    echo (string %message local "> killed by >>>") local
    echo %exception local
    echo %ex local
    print (string %message local "<<<") local

    return

M sample/asm/watchdog/death_message.asm => sample/asm/watchdog/death_message.asm +3 -3
@@ 21,18 21,18 @@
    allocate_registers %5 local

    .name: %iota death_message
    .name: %iota exception
    .name: %iota ex
    .name: %iota aborted_function

    move %death_message local %0 parameters
    structremove %exception local %death_message local (atom %exception local 'exception') local
    structremove %ex local %death_message local (atom %ex local 'exception') local
    structremove %aborted_function local %death_message local (atom %aborted_function local 'function') local

    .name: %iota message
    echo (string %message local "[WARNING] process '") local
    echo %aborted_function local
    echo (string %message local "' killed by >>>") local
    echo %exception local
    echo %ex local
    print (string %message local "<<<") local

    return

M sample/asm/watchdog/restarting_process.asm => sample/asm/watchdog/restarting_process.asm +21 -19
@@ 17,16 17,16 @@
;   along with Viua VM.  If not, see <http://www.gnu.org/licenses/>.
;

.function: watchdog_process/1
    allocate_registers %6 local
.function: watchdog_process/2
    allocate_registers %8 local

    .name: %iota death_message
    .name: %iota exception
    .name: %iota ex
    .name: %iota aborted_function
    .name: %iota params

    move %death_message local %0 parameters
    structremove %exception local %death_message local (atom %exception local 'exception') local
    structremove %ex local %death_message local (atom %ex local 'exception') local
    structremove %aborted_function local %death_message local (atom %aborted_function local 'function') local
    structremove %params local %death_message local (atom %params local 'parameters') local



@@ 35,11 35,15 @@
    echo %aborted_function local
    echo %params local
    echo (string %message local "' killed by >>>") local
    echo %exception local
    echo %ex local
    print (string %message local "<<<") local

    .name: %iota i
    frame ^[(move %0 arguments (integer %iota local 42) local) (move %1 arguments (integer %iota local 1) local)]
    .name: iota i
    move %i local %1 parameters

    frame %2
    move %0 arguments %i local
    move %1 arguments (integer %iota local 1) local
    process void a_division_executing_process/2

    return


@@ 48,9 52,6 @@
.function: a_detached_concurrent_process/0
    allocate_registers %2 local

    frame %1
    watchdog watchdog_process/1

    frame ^[(move %0 arguments (integer %1 local 32) local)]
    call std::misc::cycle/1



@@ 90,21 91,22 @@
.function: a_division_executing_process/2
    allocate_registers %5 local

    frame %1
    watchdog watchdog_process/1

    frame ^[(move %0 arguments (integer %1 local 128) local)]
    call std::misc::cycle/1

    .name: 1 divide_what
    .name: iota divide_what
    move %divide_what local %0 parameters

    .name: 2 divide_by
    .name: iota divide_by
    move %divide_by local %1 parameters

    .name: 3 zero
    .name: iota zero
    izero %zero local

    frame %2
    copy %1 arguments %divide_what local
    watchdog watchdog_process/2

    frame ^[(move %0 arguments (integer %4 local 128) local)]
    call std::misc::cycle/1

    if (eq %4 local %divide_by local %zero local) local +1 __after_throw
    throw (string %4 local "cannot divide by zero") local
    .mark: __after_throw

M sample/types/Pointer/check_if_is_expired.asm => sample/types/Pointer/check_if_is_expired.asm +3 -2
@@ 17,15 17,16 @@
;   along with Viua VM.  If not, see <http://www.gnu.org/licenses/>.
;

.signature: Pointer::expired/1

.function: isExpired/1
    allocate_registers %4 local

    move %1 local %0 parameters

    not %2 local (ptrlive %2 local %1 local) local

    echo (string %3 local "expired: ") local
    move %0 (print %2 local) local

    return
.end


M scripts/compile => scripts/compile +2 -0
@@ 40,6 40,8 @@ elif [[ $MODE == 'fast' ]]; then
    CXXOPTIMIZATIONFLAGS=CXXOPTIMIZATIONFLAGS=-O1
elif [[ $MODE == 'normal' ]]; then
    CXXOPTIMIZATIONFLAGS=CXXOPTIMIZATIONFLAGS=-O2
elif [[ $MODE == 'hard' ]]; then
    CXXOPTIMIZATIONFLAGS=CXXOPTIMIZATIONFLAGS=-O3
fi

echo "$0: using $JOBS jobs"

A scripts/get_code_fingerprint.sh => scripts/get_code_fingerprint.sh +5 -0
@@ 0,0 1,5 @@
#!/usr/bin/env bash

set -e

cat $(find ./include ./src -type f) | sha384sum | cut -d' ' -f1

M scripts/test_full.sh => scripts/test_full.sh +1 -1
@@ 12,7 12,7 @@ VIUA_TEST_SUITE_VALGRIND_CHECKS=0 make test
# Then, test without sanitisers but with Valgrind.
echo "Running Valgrind build"
make clean
make GENERIC_SANITISER_FLAGS= CLANG_SANITISER_FLAGS= GCC_SANITISER_FLAGS= "$@"
make CLANG_SANITISER_FLAGS= GCC_SANITISER_FLAGS= "$@"
make test

if [[ $OPTIMISED == '' ]]; then

M scripts/watch.sh => scripts/watch.sh +1 -1
@@ 26,5 26,5 @@ export CXX_EXTRA_FLAGS

while true; do
    (find ./include -name '*.h' ; find ./src/ -name '*.cpp' ; find ./sample -name '*.cpp') \
        | entr -p ./scripts/compile_and_notify.sh $1
        | entr -cp ./scripts/compile_and_notify.sh $1
done

M src/assembler/backend/op_assemblers/assemble_op_frame.cpp => src/assembler/backend/op_assemblers/assemble_op_frame.cpp +2 -3
@@ 27,8 27,7 @@ auto assemble_op_frame(Program& program,
{
    Token_index target = i + 1;

    program.opframe(
        ::assembler::operands::getint(
            ::assembler::operands::resolve_register(tokens.at(target))));
    program.opframe(::assembler::operands::getint(
        ::assembler::operands::resolve_register(tokens.at(target))));
}
}}}}  // namespace viua::assembler::backend::op_assemblers

M src/assembler/backend/op_assemblers/assemble_op_if.cpp => src/assembler/backend/op_assemblers/assemble_op_if.cpp +7 -5
@@ 18,15 18,17 @@
 */

#include <tuple>

#include <viua/assembler/backend/op_assemblers.h>

namespace viua { namespace assembler { namespace backend {
namespace op_assemblers {
auto assemble_op_if(Program& program,
                    std::vector<Token> const& tokens,
                    Token_index const i,
                    viua::bytecode::codec::bytecode_size_type const& instruction,
                    std::map<std::string, Token_index> const& marks) -> void
auto assemble_op_if(
    Program& program,
    std::vector<Token> const& tokens,
    Token_index const i,
    viua::bytecode::codec::bytecode_size_type const& instruction,
    std::map<std::string, Token_index> const& marks) -> void
{
    /*  If branch is given three operands, it means its full, three-operands
     * form is being used. Otherwise, it is short, two-operands form

M src/assembler/backend/op_assemblers/assemble_op_io_wait.cpp => src/assembler/backend/op_assemblers/assemble_op_io_wait.cpp +1 -0
@@ 18,6 18,7 @@
 */

#include <iostream>

#include <viua/assembler/backend/op_assemblers.h>

namespace viua { namespace assembler { namespace backend {

M src/assembler/backend/op_assemblers/assemble_op_jump.cpp => src/assembler/backend/op_assemblers/assemble_op_jump.cpp +7 -5
@@ 18,15 18,17 @@
 */

#include <tuple>

#include <viua/assembler/backend/op_assemblers.h>

namespace viua { namespace assembler { namespace backend {
namespace op_assemblers {
auto assemble_op_jump(Program& program,
                      std::vector<Token> const& tokens,
                      Token_index const i,
                      viua::bytecode::codec::bytecode_size_type const& instruction,
                      std::map<std::string, Token_index> const& marks) -> void
auto assemble_op_jump(
    Program& program,
    std::vector<Token> const& tokens,
    Token_index const i,
    viua::bytecode::codec::bytecode_size_type const& instruction,
    std::map<std::string, Token_index> const& marks) -> void
{
    /*  Jump instruction can be written in two forms:
     *

M src/assembler/frontend/gather.cpp => src/assembler/frontend/gather.cpp +1 -0
@@ 18,6 18,7 @@
 */

#include <iostream>

#include <viua/assembler/frontend/parser.h>
#include <viua/cg/assembler/assembler.h>
#include <viua/front/asm.h>

M src/assembler/frontend/parser.cpp => src/assembler/frontend/parser.cpp +18 -17
@@ 19,17 19,19 @@

#include <iostream>
#include <stdexcept>
#include <limits>

#include <viua/assembler/frontend/parser.h>
#include <viua/bytecode/maps.h>
#include <viua/cg/assembler/assembler.h>
#include <viua/support/string.h>


using viua::bytecode::codec::Register_set;
using viua::cg::lex::Invalid_syntax;
using viua::cg::lex::Token;
using viua::cg::lex::Traced_syntax_error;
using viua::internals::Access_specifier;
using viua::bytecode::codec::Register_set;


// This value is completely arbitrary.


@@ 138,14 140,14 @@ auto viua::assembler::frontend::parser::parse_operand(
        ri->add(tokens.at(i));  // add index token

        if (str::isnum(tok.substr(1), false)) {
            constexpr auto max_allowed =
                std::numeric_limits<viua::bytecode::codec::register_index_type>::max();
            constexpr auto max_allowed = std::numeric_limits<
                viua::bytecode::codec::register_index_type>::max();
            try {
                /*
                 * We check the string value here since it is not susceptible to
                 * wraparound. If we checked the index value we would access a
                 * value that was potentially tainted by wraparound - which could
                 * lead to a false sense of security here, and weird error
                 * value that was potentially tainted by wraparound - which
                 * could lead to a false sense of security here, and weird error
                 * messages like "cannot access register 0 with 0 allocated"
                 * while the underlined source clearly states 65536.
                 *


@@ 155,23 157,22 @@ auto viua::assembler::frontend::parser::parse_operand(
                 */
                auto const actual_tried = std::stoull(tok.substr(1));
                if (actual_tried > max_allowed) {
                    throw std::out_of_range{"tried to allocate too many registers"};
                    throw std::out_of_range{
                        "tried to allocate too many registers"};
                }
                ri->index =
                    static_cast<decltype(ri->index)>(actual_tried);
                ri->index = static_cast<decltype(ri->index)>(actual_tried);
            } catch (std::out_of_range&) {
                throw Invalid_syntax{
                    tokens.at(0),
                    "register index outside of defined range (max allowed "
                    "register index is "
                        + std::to_string(max_allowed)
                        + ')'};
                        + std::to_string(max_allowed) + ')'};
            }
            ri->resolved = true;
        } else if (str::isnum(tok.substr(1), true)) {
            throw Invalid_syntax(tokens.at(0),
                                 "register indexes cannot be negative: "
                                     + tok.substr(1));
            throw Invalid_syntax(
                tokens.at(0),
                "register indexes cannot be negative: " + tok.substr(1));
        } else {
            // FIXME Throw this error during register usage analysis, when we
            // have a full map of names built so "did you mean...?" note can be


@@ 399,7 400,7 @@ auto viua::assembler::frontend::parser::parse_directive(
{
    auto i = decltype(tokens)::size_type{0};

    if (not::assembler::utils::lines::is_directive(tokens.at(0))) {
    if (not ::assembler::utils::lines::is_directive(tokens.at(0))) {
        auto error = Invalid_syntax(tokens.at(0), "unknown directive");
        if (auto suggestion =
                str::levenshtein_best(tokens.at(i),


@@ 517,7 518,7 @@ auto viua::assembler::frontend::parser::parse_function(

    ib.name = tokens.at(i);

    if (not::assembler::utils::is_valid_function_name(ib.name)) {
    if (not ::assembler::utils::is_valid_function_name(ib.name)) {
        throw Invalid_syntax(ib.name,
                             ("invalid function name: " + ib.name.str()));
    }


@@ 555,7 556,7 @@ auto viua::assembler::frontend::parser::parse_closure(
    ib.closure = true;
    ib.name    = tokens.at(i);

    if (not::assembler::utils::is_valid_function_name(ib.name)) {
    if (not ::assembler::utils::is_valid_function_name(ib.name)) {
        throw Invalid_syntax(ib.name,
                             ("invalid function name: " + ib.name.str()));
    }


@@ 646,7 647,7 @@ auto viua::assembler::frontend::parser::parse(std::vector<Token> const& tokens)
            if (tokens.at(i) == "\n") {
                throw Invalid_syntax(tokens.at(i - 1), "missing function name");
            }
            if (not::assembler::utils::is_valid_function_name(tokens.at(i))) {
            if (not ::assembler::utils::is_valid_function_name(tokens.at(i))) {
                throw Invalid_syntax(tokens.at(i), "not a valid function name");
            }
            parsed.function_signatures.push_back(tokens.at(i++));

M src/assembler/frontend/static_analyser/Closure.cpp => src/assembler/frontend/static_analyser/Closure.cpp +4 -2
@@ 27,6 27,8 @@ auto Closure::define(Register const r, viua::cg::lex::Token const t) -> void
        r, std::pair<viua::cg::lex::Token, Register>(t, r));
}

Closure::Closure() : name("") {}
Closure::Closure(std::string n) : name(n) {}
Closure::Closure() : name("")
{}
Closure::Closure(std::string n) : name(n)
{}
}}}}  // namespace viua::assembler::frontend::static_analyser

M src/assembler/frontend/static_analyser/Register.cpp => src/assembler/frontend/static_analyser/Register.cpp +1 -0
@@ 18,6 18,7 @@
 */

#include <sstream>

#include <viua/assembler/frontend/static_analyser.h>

namespace viua { namespace assembler { namespace frontend {

M src/assembler/frontend/static_analyser/Register_usage_profile.cpp => src/assembler/frontend/static_analyser/Register_usage_profile.cpp +9 -3
@@ 18,6 18,7 @@
 */

#include <algorithm>

#include <viua/assembler/frontend/static_analyser.h>

namespace viua { namespace assembler { namespace frontend {


@@ 31,7 32,10 @@ auto Register_usage_profile::fresh(Register const r) const -> bool
    return fresh_registers.count(r);
}

auto Register_usage_profile::defresh() -> void { fresh_registers.clear(); }
auto Register_usage_profile::defresh() -> void
{
    fresh_registers.clear();
}
auto Register_usage_profile::erase_arguments(Token const t) -> void
{
    auto args_regs = std::vector<Register>{};


@@ 56,7 60,8 @@ auto Register_usage_profile::define(Register const r,
    if ((not in_bounds(r))
        and !(r.register_set == viua::bytecode::codec::Register_set::Global
              or r.register_set == viua::bytecode::codec::Register_set::Static
              or r.register_set == viua::bytecode::codec::Register_set::Parameters)) {
              or r.register_set
                     == viua::bytecode::codec::Register_set::Parameters)) {
        /*
         * Do not thrown on global or static register set access.
         * There is currently no simple (or complicated) way to check if such


@@ 92,7 97,8 @@ auto Register_usage_profile::define(Register const r,
    if ((not in_bounds(r))
        and !(r.register_set == viua::bytecode::codec::Register_set::Global
              or r.register_set == viua::bytecode::codec::Register_set::Static
              or r.register_set == viua::bytecode::codec::Register_set::Parameters)) {
              or r.register_set
                     == viua::bytecode::codec::Register_set::Parameters)) {
        /*
         * Do not thrown on global or static register set access.
         * There is currently no simple (or complicated) way to check if such

M src/assembler/frontend/static_analyser/checkers/check_closure_instantiations.cpp => src/assembler/frontend/static_analyser/checkers/check_closure_instantiations.cpp +1 -0
@@ 18,6 18,7 @@
 */

#include <algorithm>

#include <viua/assembler/frontend/static_analyser.h>
#include <viua/util/range.h>


M src/assembler/frontend/static_analyser/checkers/check_for_unused_registers.cpp => src/assembler/frontend/static_analyser/checkers/check_for_unused_registers.cpp +1 -0
@@ 18,6 18,7 @@
 */

#include <sstream>

#include <viua/assembler/frontend/static_analyser.h>
#include <viua/support/string.h>


M src/assembler/frontend/static_analyser/checkers/check_for_unused_values.cpp => src/assembler/frontend/static_analyser/checkers/check_for_unused_values.cpp +1 -0
@@ 19,6 19,7 @@

#include <iostream>
#include <sstream>

#include <viua/assembler/frontend/static_analyser.h>
#include <viua/support/string.h>


M src/assembler/frontend/static_analyser/checkers/check_op_allocate_registers.cpp => src/assembler/frontend/static_analyser/checkers/check_op_allocate_registers.cpp +1 -0
@@ 20,6 20,7 @@
#include <iostream>
#include <limits>
#include <string>

#include <viua/assembler/frontend/static_analyser.h>

using viua::assembler::frontend::parser::Instruction;

M src/assembler/frontend/static_analyser/checkers/check_op_arithmetic.cpp => src/assembler/frontend/static_analyser/checkers/check_op_arithmetic.cpp +7 -2
@@ 19,6 19,7 @@

#include <string>
#include <vector>

#include <viua/assembler/frontend/static_analyser.h>
#include <viua/support/string.h>



@@ 60,8 61,12 @@ auto check_op_arithmetic(Register_usage_profile& register_usage_profile,
    assert_type_of_register<viua::internals::Value_types::NUMBER>(
        register_usage_profile, *rhs);

    auto val       = Register(*result);
    val.value_type = register_usage_profile.at(*lhs).second.value_type;
    auto val            = Register(*result);
    auto const val_type = register_usage_profile.at(*lhs).second.value_type;
    val.value_type =
        (static_cast<bool>(val_type & viua::internals::Value_types::POINTER)
             ? (val_type ^ viua::internals::Value_types::POINTER)
             : val_type);
    register_usage_profile.define(val, result->tokens.at(0));
}
}}}}}  // namespace viua::assembler::frontend::static_analyser::checkers

M src/assembler/frontend/static_analyser/checkers/check_op_atom.cpp => src/assembler/frontend/static_analyser/checkers/check_op_atom.cpp +11 -3
@@ 18,6 18,7 @@
 */

#include <string>

#include <viua/assembler/frontend/static_analyser.h>

using viua::assembler::frontend::parser::Instruction;


@@ 28,6 29,7 @@ auto check_op_atom(Register_usage_profile& register_usage_profile,
                   Instruction const& instruction) -> void
{
    using viua::assembler::frontend::parser::Atom_literal;
    using viua::assembler::frontend::parser::Text_literal;

    auto operand = get_operand<Register_index>(instruction, 0);