We are developing CRVJA, a tool suite that brings AMOS BASIC programs to the browser by translating their source code into JavaScript. In this blog post we focus on deciding which AMOS commands to implement next. AMOS Professional has more than 700 commands. Adding rules to recognize how they are written is comparatively manageable, but implementing their semantic actions, the JavaScript code that reproduces their behaviour, takes much more work.

We therefore need to choose a useful subset of a language. Our initial priorities follow the manual's categories, such as instructions, functions, and structures, but those groups still leave many commands to implement. To refine that choice, we created amos-code-analysis to measure command usage in programs we collect from websites and repositories. The goal is to identify which implementation work could help more AMOS programs run in CRVJA.

Evidence from other languages

Researchers have long used usage analysis to decide what a language implementation should support first. Work on GCC builtins is the closest parallel to our problem: after analysing C projects, the authors found that prioritizing operations that unlock additional projects works better than ranking each operation by popularity alone [1]. Python offers a similar lesson. Examining millions of source files, Yang et al. found that dynamic execution is rare, while decorators and context managers are widespread, which makes the latter two relevant to a minimal subset for analysis tools [2].

programming-languages.jpg

Other work describes how languages are used in practice. Bash scripts lean heavily on file, path, and directory utilities, which dominate the commands the authors measured [3]. Java's newer features, meanwhile, are adopted unevenly: developers convert existing code to them, yet many places where they could be applied remain untouched [4]. Together, these results suggest a practical starting point for CRVJA: measure what real AMOS programs use, then decide what to implement.

The AMOS implementation problem

In AMOS, a BASIC language for the Commodore Amiga, this choice involves commands for graphics, sound, input, and program logic. The AMOS Professional command index groups them by category. An instruction, such as Plot, performs an operation; a function, such as Abs, returns a value; and a structure, such as If or For, expresses conditions or loops. The index also distinguishes reserved variables and commands for animation and dialogue interfaces. These categories help us organize the work. Usage analysis can then help us choose priorities within those groups.

Supporting each command involves two tasks: recognizing how it is written and reproducing what it does. A grammar describes the first through syntax rules. Many AMOS commands follow documented patterns that reuse our existing rules for expressions and separators. For example, Plot has this rule:

plot: 'Plot' expression COMMA expression;

This says that Plot takes two expressions separated by a comma, as in Plot 10,20. ANTLR, our parser generator, turns the grammar into code that recognizes those patterns. We still need to handle ambiguities, syntax variations, and keyword boundaries, but ANTLR generates the parsing machinery. Terence Parr's The Definitive ANTLR 4 Reference (2013) explains this separation between grammar rules and the application code that gives recognized constructs their behaviour [5].

The second task, implementing semantics, is where the behaviour comes in. For Plot, the generated JavaScript must evaluate coordinates, use the current drawing colour and palette, and update the browser representation of the AMOS screen. Other commands depend on keyboard events, audio, timing, or sprite assets, often sharing state with the program. We must understand these effects, reproduce them through browser facilities, and check their correctness. These semantic actions reside in CRVJA's JavaScript listener and visitor handlers, code that processes the structures recognized by the parser.

Reusing the grammar for analysis

That separation makes the grammar useful for analysis even while command implementations are unfinished. Our amos-code-analysis tool uses it to identify commands in a collection of source files. We first organize those files into a dataset and load a catalog of command names and categories. CRVJA's ANTLR lexer and parser then process each file, producing a parse tree that organizes its source according to the grammar.

We walk through the tree with an analysis listener that responds to recognized keywords. It passes eligible command names to enterCommand, a helper that increments matching catalog entries. Each file starts with fresh counters. We record the counts and their source files, then combine those records into a dataset summary.

parse-tree

The counts measure static source occurrences: how many times a command is written in the code. A command written once inside a loop contributes one occurrence, even if the program executes it thousands of times. This helps us identify commands present in the source without needing to run the program or implement every command's JavaScript behaviour first.

The current analyser targets the Instruction category, with incomplete counting coverage. Within that scope, its reports let us compare usage across files and projects.

From source files to usage tables

The tool needs to preserve where each occurrence came from so we can compare usage across files and projects. Its input is one dataset directory, with a separate subdirectory for each project. Within each project, it searches for .asc and .txt files, including files in nested directories. Extensions are case-insensitive. Files directly in the dataset root are ignored.

Consider this illustrative dataset, containing two projects and three short source files. These fragments demonstrate the reports; they are not collected research data.

example_dataset/
├── greeting/
│   └── main.asc
└── triangle/
    ├── helper.txt
    └── main.asc

Each file contains a few occurrences of Ink or Text:

greeting/main.asc

Text 0,0,"Hi"

triangle/main.asc

Ink 1
Text 10,20,"Hello"
Ink 2

triangle/helper.txt

Ink 3

To analyse it, we run this command from the tool directory:

node main.js --input ./datasets/example_dataset

The analyser records counts for each file and uses those records to produce two reports.

CRVJA-bpmn-code-analysis.jpg

Code analysis process

The reports are saved as CSV tables in the tool's output directory, ready to open in a spreadsheet. The first, analysis.csv, shows where each instruction occurs:

COMMAND CATEGORY COUNT PROJECT FILE_PATH
TEXT Instruction 1 greeting main.asc
INK Instruction 1 triangle helper.txt
INK Instruction 2 triangle main.asc
TEXT Instruction 1 triangle main.asc

The third row tells us that INK occurs twice in triangle/main.asc. COMMAND and CATEGORY identify the catalog entry; COUNT gives its occurrences. PROJECT names the project, and FILE_PATH locates the file within it, allowing us to trace totals back to their source.

The second report, aggregate.csv, brings those counts together by command and category:

COMMAND CATEGORY TOTAL_COUNT PROJECT_COUNT FILE_COUNT
INK Instruction 3 1 2
TEXT Instruction 2 2 2

TOTAL_COUNT sums occurrences, PROJECT_COUNT counts distinct projects containing the command, and FILE_COUNT counts distinct files. A file is identified by both its project and relative path, so the two main.asc files remain separate.

Here, INK occurs more often, while TEXT appears in both projects. Ranking total occurrences favours INK; ranking project prevalence favours TEXT. A program may still need several unsupported commands before it can run. As the GCC builtin study illustrates, we should also ask which command combinations would help us support more complete programs.

Each run replaces the reports with results for the selected dataset. Aggregate rows are ordered by command and category. To turn them into priorities, we must consider the measurements alongside program requirements and implementation effort.

What comes next

To make those decisions, we need reliable measurements from a varied collection of programs. We are still developing the tool. Our next steps are to complete the grammar and build a documented AMOS dataset, recording sources and identifying duplicates so that copies of one program do not appear to be independent evidence of widespread usage.

We also need to check the counts against examples counted by hand. The current method misses some recognized commands and does not always distinguish variants or contexts. We must report incomplete parses, because recovering from unsupported syntax can produce partial counts.

We have not yet established a ranking of AMOS commands. For CRVJA, the practical meaning of “important” is tied to our goal: making more AMOS programs usable in the browser with the implementation work we can undertake. Combining the manual's categories with observed usage and program requirements will give us a clearer basis for choosing the subset to support next.

References

  • [1] Rigger, M., Marr, S., Adams, B., and Mössenböck, H. (2019). Understanding GCC Builtins to Develop Better Tools. ESEC/FSE, pp. 74–85. DOI.
  • [2] Yang, Y., Milanova, A., and Hirzel, M. (2022). Complex Python Features in the Wild. MSR, pp. 282–293. DOI.
  • [3] Dong, Y., Li, Z., Tian, Y., Sun, C., Godfrey, M. W., and Nagappan, M. (2023). Bash in the Wild: Language Usage, Code Smells, and Bugs. ACM TOSEM, 32(1), Article 8. DOI.
  • [4] Dyer, R., Rajan, H., Nguyen, H. A., and Nguyen, T. N. (2014). Mining Billions of AST Nodes to Study Actual and Potential Usage of Java Language Features. ICSE, pp. 779–790. DOI.
  • [5] Parr, T. (2013). The Definitive ANTLR 4 Reference. The Pragmatic Bookshelf. Publisher.