From 0c4f640cd7647df712256f9c16af2ac657bb4094 Mon Sep 17 00:00:00 2001 From: William Baker Date: Sun, 29 Sep 2024 13:55:02 -0400 Subject: [PATCH] more documentation, mostly --- CHANGELOG.md | 2 +- README.md | 31 +++++++++++++++++++++++++++++++ src/assembly_scanner.cpp | 11 +++++++++-- tests/cli/invalid_flags/index.sh | 2 ++ wasm/in.civet | 1 + 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa68d43..aa24337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file. See [Keep a ### Added -- The interpreter can now handle assembly syntax with the `-A` flag. +- The interpreter can now handle assembly syntax, with the `-A` flag in the command line and a checkbox in the online interpreter. Currently, interactive debugging of assembly is not supported in the web interpreter. ### Changed diff --git a/README.md b/README.md index e4d95c4..43e96c8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Trilangle is a 2-D, stack-based programming language inspired by [Hexagony]. > - [Threading](#threading) > - [Interpreter flags](#interpreter-flags) > - [The disassembler](#the-disassembler) +> - [Assembly syntax](#assembly-syntax) > - [C compiler](#c-compiler) > - [Sample programs](#sample-programs) > - [cat](#cat) @@ -224,6 +225,36 @@ For example, when passing [the cat program below](#cat) with the flags `-Dn`, th 2.2: EXT ``` +### Assembly syntax + +In addition to producing this syntax, Trilangle is capable of interpreting this syntax. Currently, the output with `--hide-nops` is not guaranteed to be interpretable, as it may be missing jump targets. Each line can maximally consist of a label, an instruction, and a comment. The syntax can be described with the following extended Backus-Naur form: + +``` +program = line, {newline, line}; +line = [label, [":"]], [multiple_whitespace, instruction], {whitespace}, [comment]; + +newline = ? U+000A END OF LINE ?; +tab = ? U+0009 CHARACTER TABULATION ?; +whitespace = " " | ? U+000D CARRIAGE RETURN ? | tab; +non_whitespace = ? Any single unicode character not in 'newline' or 'whitespace' ?; +multiple_whitespace = whitespace, {whitespace}; + +label = non_whitespace, {non_whitespace}; +comment = ";", {non_whitespace | whitespace}; + +instruction = instruction_with_target | instruction_with_argument | plain_instruction; +instruction_with_target = ("BNG" | "TSP" | "JMP"), multiple_whitespace, label; +instruction_with_argument = ("PSI" | "PSC"), multiple_whitespace, number_literal; +plain_instruction = ? Any three-character instruction besides the five already covered ?; + +number_literal = character_literal | decimal_literal | hex_literal; +character_literal = "'", (non_whitespace | tab), "'"; +decimal_literal = "#", decimal_digit; +hex_literal = "0x", hex_digit, {hex_digit}; +decimal_digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; +hex_digit = "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | decimal_digit; +``` + ## C compiler When using the `-c` flag, the input program will be translated into C code. The C code is not meant to be idiomatic or easy to read, as it is a literal translation of the input. Optimizers such as those used by clang and GCC tend to do a good job of improving the program, in some cases removing the heap allocation altogether; MSVC does not. diff --git a/src/assembly_scanner.cpp b/src/assembly_scanner.cpp index 06b23b3..77ab98d 100644 --- a/src/assembly_scanner.cpp +++ b/src/assembly_scanner.cpp @@ -165,14 +165,21 @@ NONNULL_PTR(const std::vector)>) assembly_s } arg_value = static_cast(ul); } else if (argument[0] == '#' && argument.size() == 2) { - arg_value = argument[1]; - if (arg_value < (int24_t)'0' || arg_value > (int24_t)'9') { + arg_value = static_cast(argument[1] - '0'); + if (arg_value < INT24_C(0) || arg_value > INT24_C(9)) { invalid_literal(argument); } } else { invalid_literal(argument); } + if (opcode == instruction::operation::PSI) { + // PSI expects to be given the digit, not the actual value + auto p = arg_value.add_with_overflow('0'); + assert(!p.first); + arg_value = p.second; + } + instruction::argument arg; arg.number = arg_value; add_instruction({ opcode, arg }); diff --git a/tests/cli/invalid_flags/index.sh b/tests/cli/invalid_flags/index.sh index d2f98ed..652fff5 100755 --- a/tests/cli/invalid_flags/index.sh +++ b/tests/cli/invalid_flags/index.sh @@ -11,6 +11,8 @@ invalid_flags=( -ae -aD # --show-stack without --debug -s + # --hide-nops without --disassemble + -n ) for flag in "${invalid_flags[@]}" diff --git a/wasm/in.civet b/wasm/in.civet index 058052d..d9d1780 100644 --- a/wasm/in.civet +++ b/wasm/in.civet @@ -397,6 +397,7 @@ do elements.urlButton.onclick = generateURL elements.program.addEventListener 'input', hideUrl, { +passive } elements.includeInput.addEventListener 'change', hideUrl, { +passive } + elements.assembly.addEventListener 'change', hideUrl, { +passive } elements.stdin.addEventListener 'change', => hideUrl() if elements.includeInput.checked, { +passive } // Allow the header itself, or noninteractable children (e.g. the select icon)