
Compact educational BASIC dialect compiling to MK-61 RPN instructions, offering readable syntax, register-aware allocation, RPN code generation and a fluent parser-to-instruction translation pipeline.
Micro Basic is a compact, educational programming language created specifically for the virtual machine of the Elektronika MK-61 programmable RPN calculator.
Unlike classic BASIC implementations that target general-purpose computers, Micro Basic is designed to be translated into executable instructions for the MK-61 virtual machine. Every language construct ultimately corresponds to one or more calculator instructions.
The language intentionally provides a modern and readable BASIC syntax while preserving the hardware limitations of the original calculator. As a result, some language features differ from traditional BASIC implementations in order to match the capabilities of the MK-61 architecture.
So Micro Basic is not intended to be a general-purpose programming language.
Its primary objective is to make development for the Elektronika MK-61 significantly easier without hiding the architectural nature of the original machine. From this point of view, rather than abstracting away the hardware, Micro Basic embraces it.
Understanding the calculator's registers, stack, and execution model allows programmers to write faster and more efficient programs while benefiting from a modern, readable syntax.
Micro Basic is therefore not an emulator of Microsoft BASIC, GW-BASIC or Sinclair BASIC, but rather a high-level language that compiles into the instruction set of the MK-61 virtual machine.
Happy coding with Micro Basic!
[versions]
mk61-micro-basic = "0.1.1"
[libraries]
mk61-micro-basic = { module = "io.github.valiuh.mk61:micro-basic", version.ref = "mk61-micro-basic" }Then consume it in build.gradle.kts:
dependencies {
implementation(libs.mk61.micro.basic)
}Gradle Groovy DSL:
dependencies {
implementation "io.github.valiuh.mk61:micro-basic:0.1.1"
}Maven:
<dependency>
<groupId>io.github.valiuh.mk61</groupId>
<artifactId>micro-basic</artifactId>
<version>0.1.1</version>
</dependency>The Kotlin DSL provides a fluent translation pipeline from Micro Basic source code to MK-61 virtual machine instructions (List<String>).
Each step transforms the program to the next stage of compilation:
private fun translate(scriptName: String): List<String> =
loadTestScript(scriptName = scriptName)
.tokenize()
.parseWithParser(parser = LLParser())
.checkSemantics() // optional
.allocateMemory()
.generateOrElse { errors -> fail(errors.formatMessages()) }
private fun execute(program: List<String>): Mk61 =
Mk61().apply {
uploadProgram(program.joinToString("\n"))
calculate()
}
val program = translate("factorial.mb61")
val vmState = execute(program)LLParser is an implementation of an LL parser and implements the Parser interface.
Because parseWithParser() accepts Parser, you can provide any parser implementation compatible with that interface.
.checkSemantics() is optional. If you skip semantic verification, you can go directly to memory allocation and generation.
When semantic (or allocation-related semantic) errors are detected, generateOrElse { errors -> ... } calls your error handler, for example:
.generateOrElse { errors -> fail(errors.formatMessages()) }If you do not need this error callback style, you can also generate directly from an AST without generateOrElse:
val instructions = source
.tokenize()
.parse(parser = LLParser())
.generate()The output of these flows is an MK-61 instruction list that can be uploaded and executed on the virtual machine.
Micro Basic intentionally differs from traditional BASIC dialects.
| Feature | Micro Basic |
|---|---|
| Numeric variables | ✔ |
| Strings | ✘ |
| Arrays | ✘ |
| Dynamic memory | ✘ |
| Heap | ✘ |
| Local variables | ✘ |
| Call stack | ✘ |
| Recursion | ✘ |
| Register allocation | ✔ |
| RPN code generation | ✔ |
| MK-61 compatible | ✔ |
Micro Basic should be viewed as a higher-level abstraction over the MK-61 instruction set.
Every language construct eventually becomes one or more calculator instructions.
Examples
| Micro Basic | Conceptual MK-61 Operation |
|---|---|
LET a = x |
Evaluate expression → Store in register |
INPUT a |
User input → X → Memory Register |
PRINT a |
Memory Register → X |
GOTO |
Unconditional jump |
GOSUB |
Call subroutine |
RETURN |
Return from subroutine |
IF |
Conditional branch |
FOR |
Counter initialization and conditional branching |
The language therefore remains very close to the hardware while providing a significantly more readable programming model.
MiniBasic intentionally keeps its grammar compact.
A simplified grammar is shown below.
program
statement*
statement
REM
LET
INPUT
PRINT
IF
GOTO
GOSUB
RETURN
SUB
FOR
NEXT
STOP
END
expression
literal
variable
unary-function
binary-expression
parenthesized-expression
The actual parser may implement additional internal productions required for code generation.
A Micro Basic program consists of a sequence of statements executed from top to bottom.
Example:
REM Simple example
LET value = 10
PRINT value
ENDStatements are generally written one per line.
Keywords are case-insensitive.
Line numbers are optional and may be used when explicit addressing is desired.
Comments begin with the REM keyword.
Variables are introduced using the LET statement.
LET counter = 0
LET total = 15
LET result = counter + totalVariable names may contain:
_)Both of the following naming conventions are valid:
LET counter = 0
LET Counter = 0
LET total_sum = 0
LET currentValue = 10
LET current_value = 10The language is intended to support common naming styles, including:
Unlike traditional BASIC implementations, Micro Basic does not have unlimited variables.
This limitation comes directly from the architecture of the MK-61 calculator.
The calculator contains a fixed number of programmable memory registers.
These registers are used for storing every variable in the program.
Typical register set:
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
Because the underlying hardware provides only a fixed amount of register memory, the number of simultaneously existing variables is also limited.
Every variable used anywhere in the program consumes one calculator register.
This includes:
Once all available registers have been assigned, no additional variables can be allocated.
Variables are not assigned to fixed registers by name.
Instead, the interpreter allocates registers dynamically as variables first appear in the source code.
For example:
LET a = 5
LET counter = 10
LET result = 0may internally become
| Variable | Calculator Register |
|---|---|
| a | 0 |
| counter | 1 |
| result | 2 |
Another program
LET temperature = 20
LET average = 5may become
| Variable | Calculator Register |
|---|---|
| temperature | 0 |
| average | 1 |
The mapping is determined solely by declaration order, not by variable names.
Although variable names are completely free, programs intended for the MK-61 often benefit from naming variables according to their associated register.
For example:
LET r0 = 0
LET r1 = 0
LET r2 = 0
LET r3 = 0This naming convention makes it easier for programmers to understand how variables are mapped onto the calculator's physical memory.
The compiler is free to allocate registers independently, but using register-oriented names improves readability for developers familiar with the MK-61 architecture.
Micro Basic does not create local variable scopes.
Variables exist in a single global register space shared by the entire program.
Variables declared inside loops or subroutines occupy exactly the same register pool as variables declared in the main program.
For example,
LET a = 10
SUB Square
LET temp = a * a
RETURNBoth a and temp consume calculator registers.
There is no automatic release of registers when leaving a subroutine.
For this reason, programmers are encouraged to reuse variables whenever possible.
Micro Basic provides two high-level input/output statements.
INPUT value
PRINT valueUnlike traditional BASIC systems, these statements do not represent console input or console output.
The MK-61 has:
Instead, the calculator provides a numeric keyboard together with the calculator's X register, whose value is shown on the display.
MiniBasic therefore interprets INPUT and PRINT as abstractions over operations involving register X.
INPUT valueExecution model:
value.Conceptually this is equivalent to
User input
↓
Register X
↓
Memory Register(value)
The generated calculator instructions are equivalent to:
X → П(register)
where register is the calculator register assigned to the variable.
PRINT valueExecution model:
value is loaded into register X.Conceptually:
Memory Register(value)
↓
Register X
↓
Calculator Display
Thus PRINT is not a text output operation.
Instead, it is an instruction that makes the numeric value visible by moving it into the calculator's display register.
Micro Basic provides two different execution control statements.
Terminates program execution.
ENDTemporarily halts execution while preserving the current program state.
Execution may later continue depending on the runtime environment.
STOPBoth statements are translated into their corresponding MK-61 instructions.
Micro Basic evaluates arithmetic and logical expressions using standard infix notation.
Examples:
LET a = 2 + 3
LET b = a * 5
LET c = (a + b) / 2Expressions are translated into Reverse Polish Notation (RPN) instructions suitable for execution on the MK-61 stack machine.
The compiler is responsible for generating the appropriate stack manipulation instructions required by the calculator.
| Operator | Description |
|---|---|
+ |
Addition |
- |
Subtraction |
* |
Multiplication |
/ |
Division |
^ |
Exponentiation |
Example
LET result = (a + b) * cRelational operators return logical values used by conditional statements.
| Operator | Description |
|---|---|
= |
Equal |
<> |
Not equal |
< |
Less than |
<= |
Less than or equal |
> |
Greater than |
>= |
Greater than or equal |
Example
IF value > 10 THEN
PRINT value
ENDMicro Basic supports logical operations.
| Operator | Description |
|---|---|
AND |
Logical AND |
OR |
Logical OR |
NOT |
Logical NOT |
XOR |
Exclusive OR |
Example
IF a > 0 AND b > 0 THEN
PRINT a
ENDParentheses may be used to control operator precedence.
LET result = (a + b) * (c - d)The compiler evaluates parenthesized expressions first before translating them into stack operations.
Micro Basic provides conditional execution using the IF statement.
IF a > b THEN
PRINT a
ENDOptionally,
IF a > b THEN
PRINT a
ELSE
PRINT b
ENDThe compiler generates conditional branch instructions equivalent to the calculator's conditional jump commands.
Micro Basic supports direct program jumps using GOTO.
GOTO 200Unlike higher-level language constructs, GOTO transfers execution directly to the specified program address.
The target may be either
The generated code is translated directly into the corresponding MK-61 jump instruction.
Micro Basic supports reusable program fragments using subroutines.
Two different syntaxes are available.
GOSUB 200Calls a subroutine located at an explicit program address.
Execution continues until a matching RETURN instruction is encountered.
RETURNReturns execution to the instruction immediately following the corresponding GOSUB.
Micro Basic also supports named subroutines.
SUB Square
LET result = value * value
RETURNUnlike GOSUB, the programmer specifies a symbolic name rather than a numeric address.
The compiler resolves the symbolic name into the corresponding program address during compilation.
Internally,
SUB Squareis simply another way of defining a jump target.
Therefore,
GOSUB 250and
GOSUB Squareare conceptually equivalent after compilation.
The first uses an explicit address.
The second uses a symbolic label that the compiler converts into an address.
The purpose of named subroutines is improved readability rather than additional runtime functionality.
Variables declared inside a subroutine are not local variables.
For example,
LET value = 5
SUB Square
LET temp = value * value
RETURNBoth value and temp occupy calculator memory registers.
The interpreter allocates registers exactly as if both variables had been declared in the main program.
Subroutines do not receive their own register space.
MiniBasic intentionally does not support local variables.
This limitation comes directly from the architecture of the MK-61 virtual machine.
The calculator has no mechanism for creating temporary storage areas for nested procedure calls.
Consequently,
One of the most important architectural limitations inherited from the MK-61 is the absence of a true call stack.
Unlike modern processors or virtual machines, the MK-61 does not maintain:
Every subroutine executes within exactly the same memory environment as the main program.
Because there is no stack frame, the interpreter cannot create an independent address space for a called subroutine.
Instead, all program components operate on the same fixed set of calculator registers.
This explains several language limitations:
These restrictions are not language design decisions but direct consequences of the underlying MK-61 hardware architecture.
MiniBasic supports counted loops using FOR.
FOR i = 1 TO 10
PRINT i
NEXTThe increment may be explicitly specified.
FOR i = 0 TO 20 STEP 2
PRINT i
NEXTNegative increments are also allowed.
FOR i = 10 TO 1 STEP -1
PRINT i
NEXTLoop variables are ordinary program variables.
For example,
FOR i = 1 TO 10allocates register storage for i.
Loop variables are therefore subject to the same memory limitations as every other variable in the language.
They remain part of the global register allocation.
Program execution finishes when either
ENDor
STOPis reached.
END terminates execution.
MiniBasic provides a collection of built-in mathematical functions and constants.
Whenever possible, these functions are translated directly into a single MK-61 virtual machine instruction. Functions that do not have a direct hardware equivalent may be translated into a sequence of calculator instructions.
Unless otherwise specified, each function accepts a single numeric argument and returns a numeric result.
| Function | Description |
|---|---|
EXP10(x) |
Calculates (10^x). |
EXP(x) |
Calculates (e^x). |
LOG(x) |
Base-10 logarithm. |
LN(x) |
Natural logarithm. |
POW(x, y) |
Raises x to the power y. Equivalent to the ^ operator. |
Example
LET value = EXP(2)
LET power = POW(2, 8)| Function | Description |
|---|---|
SIN(x) |
Sine |
COS(x) |
Cosine |
TAN(x) |
Tangent |
ASIN(x) |
Arc sine |
ACOS(x) |
Arc cosine |
ATN(x) |
Arc tangent |
The angle unit (degrees or radians) depends on the current configuration of the virtual machine.
Example
LET angle = 45
LET x = SIN(angle)
LET y = COS(angle)
PRINT x
PRINT y| Function | Description |
|---|---|
ABS(x) |
Absolute value |
SQRT(x) |
Square root |
SQR(x) |
Square (x²) |
RECIP(x) |
Reciprocal (1/x) |
FLOOR(x) |
Integer part of a number |
FRAC(x) |
Fractional part of a number |
SIGN(x) |
Returns -1, 0, or 1 depending on the sign of x
|
MAX(x, y) |
Returns the larger of two values |
Example
LET root = SQRT(25)
LET square = SQR(5)
LET reciprocal = RECIP(4)
LET integerPart = FLOOR(3.75)
LET fractionalPart = FRAC(3.75)
LET largest = MAX(a, b)MiniBasic provides built-in mathematical constants.
| Constant | Description |
|---|---|
PI |
Mathematical constant π |
E |
Euler's number |
Example
LET circumference = 2 * PI * radius
LET growth = E ^ x| Function | Description |
|---|---|
RANDOM() |
Generates a pseudo-random number in the range [0, 1)
|
Example
LET value = RANDOM()The MK-61 instruction set includes several specialized functions for converting between decimal and degree-minute-second representations.
| Function | Description |
|---|---|
HM_TO_DEG(x) |
Converts degrees (hours), minutes and fractions of minutes into decimal representation |
DEG_TO_HM(x) |
Converts decimal representation into degrees (hours), minutes and fractions of minutes |
HMS_TO_DEG(x) |
Converts degrees (hours), minutes, seconds into decimal representation |
DEG_TO_HMS(x) |
Converts decimal representation into degrees (hours), minutes and seconds |
These functions are primarily useful for scientific and navigation calculations.
Micro Basic programs are translated into instructions executed by the MK-61 virtual machine.
Translation consists of several independent stages.
Source Code
│
▼
Lexer
│
▼
Parser
│
▼
Abstract Syntax Tree
│
▼
Semantic Analysis
│
▼
Register Allocation
│
▼
Code Generator
│
▼
MK-61 Instructions
The lexer converts the input text into a sequence of tokens.
Typical token types include
Example
Source
LET counter = counter + 1Tokens
LET
IDENTIFIER(counter)
=
IDENTIFIER(counter)
+
NUMBER(1)
The parser converts the token stream into an Abstract Syntax Tree (AST).
Example
LET result = (a + b) * cbecomes a tree similar to
Assignment
result
*
/ \
+ c
/ \
a b
The AST is independent of the target hardware and represents only the logical structure of the program.
The semantic analysis phase validates the program.
Typical checks include
Errors detected during semantic analysis prevent code generation.
One of the most important compilation stages is register allocation.
Unlike desktop programming languages, MiniBasic cannot create an unlimited number of variables.
Instead, every variable must be assigned one of the calculator's memory registers.
Allocation follows the order of first appearance.
Example
LET a = 0
LET b = 1
LET c = 2becomes
| Variable | Register |
|---|---|
| a | 0 |
| b | 1 |
| c | 2 |
This mapping is maintained throughout the generated program.
If no free registers remain, compilation fails.
The code generator transforms the AST into executable MK-61 instructions.
Example
LET result = a + bmay become conceptually
Recall a
Push
Recall b
Add
Store result
The exact instruction sequence depends on the optimization strategy and the instruction set supported by the virtual machine.
10 REM Factorial
20 INPUT n
30 LET result = 1
40 FOR i = 1 TO n
50 LET result = result * i
60 NEXT
70 PRINT result
80 END| Address | Instruction | Address | Instruction |
|---|---|---|---|
| 00 | X→П 0 |
13 | П→X 2 |
| 01 | 1 |
14 | × |
| 02 | X→П 1 |
15 | X→П 1 |
| 03 | 1 |
16 | П→X 2 |
| 04 | X→П 2 |
17 | B↑ |
| 05 | П→X 0 |
18 | 1 |
| 06 | B↑ |
19 | + |
| 07 | П→X 2 |
20 | X→П 2 |
| 08 | - |
21 | БП |
| 09 | X≥0 |
22 | 5 |
| 10 | 23 |
23 | П→X 1 |
| 11 | П→X 1 |
24 | С/П |
| 12 | B↑ |
10 REM ax² + bx + c = 0
20 INPUT a
30 INPUT b
40 INPUT c
50 LET d = b * b - 4 * a * c
60 IF d < 0 THEN
70 PRINT -1
80 ELSE
90 LET x1 = (-b + SQRT(d)) / (2 * a)
100 LET x2 = (-b - SQRT(d)) / (2 * a)
110 PRINT x1
120 PRINT x2
130 END
140 END| Address | Instruction | Address | Instruction |
|---|---|---|---|
| 00 | X→П 0 |
31 | П→X 1 |
| 01 | X→П 1 |
32 | - |
| 02 | X→П 2 |
33 | B↑ |
| 03 | П→X 1 |
34 | П→X 3 |
| 04 | B↑ |
35 | √ |
| 05 | П→X 1 |
36 | + |
| 06 | × |
37 | B↑ |
| 07 | B↑ |
38 | 2 |
| 08 | 4 |
39 | B↑ |
| 09 | B↑ |
40 | П→X 0 |
| 10 | П→X 0 |
41 | × |
| 11 | × |
42 | ÷ |
| 12 | B↑ |
43 | X→П 4 |
| 13 | П→X 2 |
44 | 0 |
| 14 | × |
45 | B↑ |
| 15 | - |
46 | П→X 1 |
| 16 | X→П 3 |
47 | - |
| 17 | П→X 3 |
48 | B↑ |
| 18 | B↑ |
49 | П→X 3 |
| 19 | 0 |
50 | √ |
| 20 | - |
51 | - |
| 21 | X<0 |
52 | B↑ |
| 22 | 29 |
53 | 2 |
| 23 | 0 |
54 | B↑ |
| 24 | B↑ |
55 | П→X 0 |
| 25 | 1 |
56 | × |
| 26 | - |
57 | ÷ |
| 27 | БП |
58 | X→П 5 |
| 28 | 61 |
59 | П→X 4 |
| 29 | 0 |
60 | П→X 5 |
| 30 | B↑ |
61 | С/П |
10 INPUT n
20 LET a = 0
30 LET b = 1
40 FOR i = 1 TO n
50 PRINT a
60 LET t = a + b
70 LET a = b
80 LET b = t
90 NEXT
100 END| Address | Instruction | Address | Instruction |
|---|---|---|---|
| 00 | X→П 0 |
16 | П→X 2 |
| 01 | 0 |
17 | + |
| 02 | X→П 1 |
18 | X→П 4 |
| 03 | 1 |
19 | П→X 2 |
| 04 | X→П 2 |
20 | X→П 1 |
| 05 | 1 |
21 | П→X 4 |
| 06 | X→П 3 |
22 | X→П 2 |
| 07 | П→X 0 |
23 | П→X 3 |
| 08 | B↑ |
24 | B↑ |
| 09 | П→X 3 |
25 | 1 |
| 10 | - |
26 | + |
| 11 | X≥0 |
27 | X→П 3 |
| 12 | 30 |
28 | БП |
| 13 | П→X 1 |
29 | 7 |
| 14 | П→X 1 |
30 | С/П |
| 15 | B↑ |
Micro Basic is a compact, educational programming language created specifically for the virtual machine of the Elektronika MK-61 programmable RPN calculator.
Unlike classic BASIC implementations that target general-purpose computers, Micro Basic is designed to be translated into executable instructions for the MK-61 virtual machine. Every language construct ultimately corresponds to one or more calculator instructions.
The language intentionally provides a modern and readable BASIC syntax while preserving the hardware limitations of the original calculator. As a result, some language features differ from traditional BASIC implementations in order to match the capabilities of the MK-61 architecture.
So Micro Basic is not intended to be a general-purpose programming language.
Its primary objective is to make development for the Elektronika MK-61 significantly easier without hiding the architectural nature of the original machine. From this point of view, rather than abstracting away the hardware, Micro Basic embraces it.
Understanding the calculator's registers, stack, and execution model allows programmers to write faster and more efficient programs while benefiting from a modern, readable syntax.
Micro Basic is therefore not an emulator of Microsoft BASIC, GW-BASIC or Sinclair BASIC, but rather a high-level language that compiles into the instruction set of the MK-61 virtual machine.
Happy coding with Micro Basic!
[versions]
mk61-micro-basic = "0.1.1"
[libraries]
mk61-micro-basic = { module = "io.github.valiuh.mk61:micro-basic", version.ref = "mk61-micro-basic" }Then consume it in build.gradle.kts:
dependencies {
implementation(libs.mk61.micro.basic)
}Gradle Groovy DSL:
dependencies {
implementation "io.github.valiuh.mk61:micro-basic:0.1.1"
}Maven:
<dependency>
<groupId>io.github.valiuh.mk61</groupId>
<artifactId>micro-basic</artifactId>
<version>0.1.1</version>
</dependency>The Kotlin DSL provides a fluent translation pipeline from Micro Basic source code to MK-61 virtual machine instructions (List<String>).
Each step transforms the program to the next stage of compilation:
private fun translate(scriptName: String): List<String> =
loadTestScript(scriptName = scriptName)
.tokenize()
.parseWithParser(parser = LLParser())
.checkSemantics() // optional
.allocateMemory()
.generateOrElse { errors -> fail(errors.formatMessages()) }
private fun execute(program: List<String>): Mk61 =
Mk61().apply {
uploadProgram(program.joinToString("\n"))
calculate()
}
val program = translate("factorial.mb61")
val vmState = execute(program)LLParser is an implementation of an LL parser and implements the Parser interface.
Because parseWithParser() accepts Parser, you can provide any parser implementation compatible with that interface.
.checkSemantics() is optional. If you skip semantic verification, you can go directly to memory allocation and generation.
When semantic (or allocation-related semantic) errors are detected, generateOrElse { errors -> ... } calls your error handler, for example:
.generateOrElse { errors -> fail(errors.formatMessages()) }If you do not need this error callback style, you can also generate directly from an AST without generateOrElse:
val instructions = source
.tokenize()
.parse(parser = LLParser())
.generate()The output of these flows is an MK-61 instruction list that can be uploaded and executed on the virtual machine.
Micro Basic intentionally differs from traditional BASIC dialects.
| Feature | Micro Basic |
|---|---|
| Numeric variables | ✔ |
| Strings | ✘ |
| Arrays | ✘ |
| Dynamic memory | ✘ |
| Heap | ✘ |
| Local variables | ✘ |
| Call stack | ✘ |
| Recursion | ✘ |
| Register allocation | ✔ |
| RPN code generation | ✔ |
| MK-61 compatible | ✔ |
Micro Basic should be viewed as a higher-level abstraction over the MK-61 instruction set.
Every language construct eventually becomes one or more calculator instructions.
Examples
| Micro Basic | Conceptual MK-61 Operation |
|---|---|
LET a = x |
Evaluate expression → Store in register |
INPUT a |
User input → X → Memory Register |
PRINT a |
Memory Register → X |
GOTO |
Unconditional jump |
GOSUB |
Call subroutine |
RETURN |
Return from subroutine |
IF |
Conditional branch |
FOR |
Counter initialization and conditional branching |
The language therefore remains very close to the hardware while providing a significantly more readable programming model.
MiniBasic intentionally keeps its grammar compact.
A simplified grammar is shown below.
program
statement*
statement
REM
LET
INPUT
PRINT
IF
GOTO
GOSUB
RETURN
SUB
FOR
NEXT
STOP
END
expression
literal
variable
unary-function
binary-expression
parenthesized-expression
The actual parser may implement additional internal productions required for code generation.
A Micro Basic program consists of a sequence of statements executed from top to bottom.
Example:
REM Simple example
LET value = 10
PRINT value
ENDStatements are generally written one per line.
Keywords are case-insensitive.
Line numbers are optional and may be used when explicit addressing is desired.
Comments begin with the REM keyword.
Variables are introduced using the LET statement.
LET counter = 0
LET total = 15
LET result = counter + totalVariable names may contain:
_)Both of the following naming conventions are valid:
LET counter = 0
LET Counter = 0
LET total_sum = 0
LET currentValue = 10
LET current_value = 10The language is intended to support common naming styles, including:
Unlike traditional BASIC implementations, Micro Basic does not have unlimited variables.
This limitation comes directly from the architecture of the MK-61 calculator.
The calculator contains a fixed number of programmable memory registers.
These registers are used for storing every variable in the program.
Typical register set:
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
Because the underlying hardware provides only a fixed amount of register memory, the number of simultaneously existing variables is also limited.
Every variable used anywhere in the program consumes one calculator register.
This includes:
Once all available registers have been assigned, no additional variables can be allocated.
Variables are not assigned to fixed registers by name.
Instead, the interpreter allocates registers dynamically as variables first appear in the source code.
For example:
LET a = 5
LET counter = 10
LET result = 0may internally become
| Variable | Calculator Register |
|---|---|
| a | 0 |
| counter | 1 |
| result | 2 |
Another program
LET temperature = 20
LET average = 5may become
| Variable | Calculator Register |
|---|---|
| temperature | 0 |
| average | 1 |
The mapping is determined solely by declaration order, not by variable names.
Although variable names are completely free, programs intended for the MK-61 often benefit from naming variables according to their associated register.
For example:
LET r0 = 0
LET r1 = 0
LET r2 = 0
LET r3 = 0This naming convention makes it easier for programmers to understand how variables are mapped onto the calculator's physical memory.
The compiler is free to allocate registers independently, but using register-oriented names improves readability for developers familiar with the MK-61 architecture.
Micro Basic does not create local variable scopes.
Variables exist in a single global register space shared by the entire program.
Variables declared inside loops or subroutines occupy exactly the same register pool as variables declared in the main program.
For example,
LET a = 10
SUB Square
LET temp = a * a
RETURNBoth a and temp consume calculator registers.
There is no automatic release of registers when leaving a subroutine.
For this reason, programmers are encouraged to reuse variables whenever possible.
Micro Basic provides two high-level input/output statements.
INPUT value
PRINT valueUnlike traditional BASIC systems, these statements do not represent console input or console output.
The MK-61 has:
Instead, the calculator provides a numeric keyboard together with the calculator's X register, whose value is shown on the display.
MiniBasic therefore interprets INPUT and PRINT as abstractions over operations involving register X.
INPUT valueExecution model:
value.Conceptually this is equivalent to
User input
↓
Register X
↓
Memory Register(value)
The generated calculator instructions are equivalent to:
X → П(register)
where register is the calculator register assigned to the variable.
PRINT valueExecution model:
value is loaded into register X.Conceptually:
Memory Register(value)
↓
Register X
↓
Calculator Display
Thus PRINT is not a text output operation.
Instead, it is an instruction that makes the numeric value visible by moving it into the calculator's display register.
Micro Basic provides two different execution control statements.
Terminates program execution.
ENDTemporarily halts execution while preserving the current program state.
Execution may later continue depending on the runtime environment.
STOPBoth statements are translated into their corresponding MK-61 instructions.
Micro Basic evaluates arithmetic and logical expressions using standard infix notation.
Examples:
LET a = 2 + 3
LET b = a * 5
LET c = (a + b) / 2Expressions are translated into Reverse Polish Notation (RPN) instructions suitable for execution on the MK-61 stack machine.
The compiler is responsible for generating the appropriate stack manipulation instructions required by the calculator.
| Operator | Description |
|---|---|
+ |
Addition |
- |
Subtraction |
* |
Multiplication |
/ |
Division |
^ |
Exponentiation |
Example
LET result = (a + b) * cRelational operators return logical values used by conditional statements.
| Operator | Description |
|---|---|
= |
Equal |
<> |
Not equal |
< |
Less than |
<= |
Less than or equal |
> |
Greater than |
>= |
Greater than or equal |
Example
IF value > 10 THEN
PRINT value
ENDMicro Basic supports logical operations.
| Operator | Description |
|---|---|
AND |
Logical AND |
OR |
Logical OR |
NOT |
Logical NOT |
XOR |
Exclusive OR |
Example
IF a > 0 AND b > 0 THEN
PRINT a
ENDParentheses may be used to control operator precedence.
LET result = (a + b) * (c - d)The compiler evaluates parenthesized expressions first before translating them into stack operations.
Micro Basic provides conditional execution using the IF statement.
IF a > b THEN
PRINT a
ENDOptionally,
IF a > b THEN
PRINT a
ELSE
PRINT b
ENDThe compiler generates conditional branch instructions equivalent to the calculator's conditional jump commands.
Micro Basic supports direct program jumps using GOTO.
GOTO 200Unlike higher-level language constructs, GOTO transfers execution directly to the specified program address.
The target may be either
The generated code is translated directly into the corresponding MK-61 jump instruction.
Micro Basic supports reusable program fragments using subroutines.
Two different syntaxes are available.
GOSUB 200Calls a subroutine located at an explicit program address.
Execution continues until a matching RETURN instruction is encountered.
RETURNReturns execution to the instruction immediately following the corresponding GOSUB.
Micro Basic also supports named subroutines.
SUB Square
LET result = value * value
RETURNUnlike GOSUB, the programmer specifies a symbolic name rather than a numeric address.
The compiler resolves the symbolic name into the corresponding program address during compilation.
Internally,
SUB Squareis simply another way of defining a jump target.
Therefore,
GOSUB 250and
GOSUB Squareare conceptually equivalent after compilation.
The first uses an explicit address.
The second uses a symbolic label that the compiler converts into an address.
The purpose of named subroutines is improved readability rather than additional runtime functionality.
Variables declared inside a subroutine are not local variables.
For example,
LET value = 5
SUB Square
LET temp = value * value
RETURNBoth value and temp occupy calculator memory registers.
The interpreter allocates registers exactly as if both variables had been declared in the main program.
Subroutines do not receive their own register space.
MiniBasic intentionally does not support local variables.
This limitation comes directly from the architecture of the MK-61 virtual machine.
The calculator has no mechanism for creating temporary storage areas for nested procedure calls.
Consequently,
One of the most important architectural limitations inherited from the MK-61 is the absence of a true call stack.
Unlike modern processors or virtual machines, the MK-61 does not maintain:
Every subroutine executes within exactly the same memory environment as the main program.
Because there is no stack frame, the interpreter cannot create an independent address space for a called subroutine.
Instead, all program components operate on the same fixed set of calculator registers.
This explains several language limitations:
These restrictions are not language design decisions but direct consequences of the underlying MK-61 hardware architecture.
MiniBasic supports counted loops using FOR.
FOR i = 1 TO 10
PRINT i
NEXTThe increment may be explicitly specified.
FOR i = 0 TO 20 STEP 2
PRINT i
NEXTNegative increments are also allowed.
FOR i = 10 TO 1 STEP -1
PRINT i
NEXTLoop variables are ordinary program variables.
For example,
FOR i = 1 TO 10allocates register storage for i.
Loop variables are therefore subject to the same memory limitations as every other variable in the language.
They remain part of the global register allocation.
Program execution finishes when either
ENDor
STOPis reached.
END terminates execution.
MiniBasic provides a collection of built-in mathematical functions and constants.
Whenever possible, these functions are translated directly into a single MK-61 virtual machine instruction. Functions that do not have a direct hardware equivalent may be translated into a sequence of calculator instructions.
Unless otherwise specified, each function accepts a single numeric argument and returns a numeric result.
| Function | Description |
|---|---|
EXP10(x) |
Calculates (10^x). |
EXP(x) |
Calculates (e^x). |
LOG(x) |
Base-10 logarithm. |
LN(x) |
Natural logarithm. |
POW(x, y) |
Raises x to the power y. Equivalent to the ^ operator. |
Example
LET value = EXP(2)
LET power = POW(2, 8)| Function | Description |
|---|---|
SIN(x) |
Sine |
COS(x) |
Cosine |
TAN(x) |
Tangent |
ASIN(x) |
Arc sine |
ACOS(x) |
Arc cosine |
ATN(x) |
Arc tangent |
The angle unit (degrees or radians) depends on the current configuration of the virtual machine.
Example
LET angle = 45
LET x = SIN(angle)
LET y = COS(angle)
PRINT x
PRINT y| Function | Description |
|---|---|
ABS(x) |
Absolute value |
SQRT(x) |
Square root |
SQR(x) |
Square (x²) |
RECIP(x) |
Reciprocal (1/x) |
FLOOR(x) |
Integer part of a number |
FRAC(x) |
Fractional part of a number |
SIGN(x) |
Returns -1, 0, or 1 depending on the sign of x
|
MAX(x, y) |
Returns the larger of two values |
Example
LET root = SQRT(25)
LET square = SQR(5)
LET reciprocal = RECIP(4)
LET integerPart = FLOOR(3.75)
LET fractionalPart = FRAC(3.75)
LET largest = MAX(a, b)MiniBasic provides built-in mathematical constants.
| Constant | Description |
|---|---|
PI |
Mathematical constant π |
E |
Euler's number |
Example
LET circumference = 2 * PI * radius
LET growth = E ^ x| Function | Description |
|---|---|
RANDOM() |
Generates a pseudo-random number in the range [0, 1)
|
Example
LET value = RANDOM()The MK-61 instruction set includes several specialized functions for converting between decimal and degree-minute-second representations.
| Function | Description |
|---|---|
HM_TO_DEG(x) |
Converts degrees (hours), minutes and fractions of minutes into decimal representation |
DEG_TO_HM(x) |
Converts decimal representation into degrees (hours), minutes and fractions of minutes |
HMS_TO_DEG(x) |
Converts degrees (hours), minutes, seconds into decimal representation |
DEG_TO_HMS(x) |
Converts decimal representation into degrees (hours), minutes and seconds |
These functions are primarily useful for scientific and navigation calculations.
Micro Basic programs are translated into instructions executed by the MK-61 virtual machine.
Translation consists of several independent stages.
Source Code
│
▼
Lexer
│
▼
Parser
│
▼
Abstract Syntax Tree
│
▼
Semantic Analysis
│
▼
Register Allocation
│
▼
Code Generator
│
▼
MK-61 Instructions
The lexer converts the input text into a sequence of tokens.
Typical token types include
Example
Source
LET counter = counter + 1Tokens
LET
IDENTIFIER(counter)
=
IDENTIFIER(counter)
+
NUMBER(1)
The parser converts the token stream into an Abstract Syntax Tree (AST).
Example
LET result = (a + b) * cbecomes a tree similar to
Assignment
result
*
/ \
+ c
/ \
a b
The AST is independent of the target hardware and represents only the logical structure of the program.
The semantic analysis phase validates the program.
Typical checks include
Errors detected during semantic analysis prevent code generation.
One of the most important compilation stages is register allocation.
Unlike desktop programming languages, MiniBasic cannot create an unlimited number of variables.
Instead, every variable must be assigned one of the calculator's memory registers.
Allocation follows the order of first appearance.
Example
LET a = 0
LET b = 1
LET c = 2becomes
| Variable | Register |
|---|---|
| a | 0 |
| b | 1 |
| c | 2 |
This mapping is maintained throughout the generated program.
If no free registers remain, compilation fails.
The code generator transforms the AST into executable MK-61 instructions.
Example
LET result = a + bmay become conceptually
Recall a
Push
Recall b
Add
Store result
The exact instruction sequence depends on the optimization strategy and the instruction set supported by the virtual machine.
10 REM Factorial
20 INPUT n
30 LET result = 1
40 FOR i = 1 TO n
50 LET result = result * i
60 NEXT
70 PRINT result
80 END| Address | Instruction | Address | Instruction |
|---|---|---|---|
| 00 | X→П 0 |
13 | П→X 2 |
| 01 | 1 |
14 | × |
| 02 | X→П 1 |
15 | X→П 1 |
| 03 | 1 |
16 | П→X 2 |
| 04 | X→П 2 |
17 | B↑ |
| 05 | П→X 0 |
18 | 1 |
| 06 | B↑ |
19 | + |
| 07 | П→X 2 |
20 | X→П 2 |
| 08 | - |
21 | БП |
| 09 | X≥0 |
22 | 5 |
| 10 | 23 |
23 | П→X 1 |
| 11 | П→X 1 |
24 | С/П |
| 12 | B↑ |
10 REM ax² + bx + c = 0
20 INPUT a
30 INPUT b
40 INPUT c
50 LET d = b * b - 4 * a * c
60 IF d < 0 THEN
70 PRINT -1
80 ELSE
90 LET x1 = (-b + SQRT(d)) / (2 * a)
100 LET x2 = (-b - SQRT(d)) / (2 * a)
110 PRINT x1
120 PRINT x2
130 END
140 END| Address | Instruction | Address | Instruction |
|---|---|---|---|
| 00 | X→П 0 |
31 | П→X 1 |
| 01 | X→П 1 |
32 | - |
| 02 | X→П 2 |
33 | B↑ |
| 03 | П→X 1 |
34 | П→X 3 |
| 04 | B↑ |
35 | √ |
| 05 | П→X 1 |
36 | + |
| 06 | × |
37 | B↑ |
| 07 | B↑ |
38 | 2 |
| 08 | 4 |
39 | B↑ |
| 09 | B↑ |
40 | П→X 0 |
| 10 | П→X 0 |
41 | × |
| 11 | × |
42 | ÷ |
| 12 | B↑ |
43 | X→П 4 |
| 13 | П→X 2 |
44 | 0 |
| 14 | × |
45 | B↑ |
| 15 | - |
46 | П→X 1 |
| 16 | X→П 3 |
47 | - |
| 17 | П→X 3 |
48 | B↑ |
| 18 | B↑ |
49 | П→X 3 |
| 19 | 0 |
50 | √ |
| 20 | - |
51 | - |
| 21 | X<0 |
52 | B↑ |
| 22 | 29 |
53 | 2 |
| 23 | 0 |
54 | B↑ |
| 24 | B↑ |
55 | П→X 0 |
| 25 | 1 |
56 | × |
| 26 | - |
57 | ÷ |
| 27 | БП |
58 | X→П 5 |
| 28 | 61 |
59 | П→X 4 |
| 29 | 0 |
60 | П→X 5 |
| 30 | B↑ |
61 | С/П |
10 INPUT n
20 LET a = 0
30 LET b = 1
40 FOR i = 1 TO n
50 PRINT a
60 LET t = a + b
70 LET a = b
80 LET b = t
90 NEXT
100 END| Address | Instruction | Address | Instruction |
|---|---|---|---|
| 00 | X→П 0 |
16 | П→X 2 |
| 01 | 0 |
17 | + |
| 02 | X→П 1 |
18 | X→П 4 |
| 03 | 1 |
19 | П→X 2 |
| 04 | X→П 2 |
20 | X→П 1 |
| 05 | 1 |
21 | П→X 4 |
| 06 | X→П 3 |
22 | X→П 2 |
| 07 | П→X 0 |
23 | П→X 3 |
| 08 | B↑ |
24 | B↑ |
| 09 | П→X 3 |
25 | 1 |
| 10 | - |
26 | + |
| 11 | X≥0 |
27 | X→П 3 |
| 12 | 30 |
28 | БП |
| 13 | П→X 1 |
29 | 7 |
| 14 | П→X 1 |
30 | С/П |
| 15 | B↑ |