1
0
Fork
You've already forked spec
0
Official language specification
Find a file
Gordinator c9776e3345 Added CAST instruction
Converts a float to an int and an int to a float.
2024年05月26日 16:09:08 +01:00
LICENSE Initial commit 2024年05月19日 15:14:14 +00:00
README.md Added CAST instruction 2024年05月26日 16:09:08 +01:00

Official JAJL Specification

Version: 1.2

Introduction

The JAJL programming language is an esolang that is designed to be simple to implement a compiler or interpreter for.

As such, an official specification is important to ensure uniformity between implementations. This document resolves that issue. It is intended as a reference for those who wish to write a JAJL compiler or interpreter, as well as a compliance test for implementations.

Basic Terminology

The Language

  • JAJL
    • The programming language.
  • Program
    • A piece of software written in JAJL.
  • Dialect
    • An implementation of JAJL that may be identical functionally, or may have differences.

Its Features

  • Memory address
    • A place in memory that stores a memory value.
    • Memory addresses range from 0000 to ffff, inclusive.
    • Most implementations use a dictionary or similar to implement it.
  • Memory value
    • The value of a memory address. Can be any of the data types described below.
  • Instruction
    • A command that the JAJL compiler or interpreter runs.
  • Stack
    • A place outside of memory used for copying memory addresses.
    • The stack is of type Integer.
    • The stack is set to 0 by default.
  • Pointer
    • Another place outside of memory that is used by commands as a workaround for the One Argument Rule.
    • The pointer 'points' to a specific memory address.
    • The pointer points to aaaa by default.
  • String buffer
    • Another place outside of memory that is used as an alternative to a string data type.
    • It is set to an empty string by default, which is NOT a JAJL data type.
  • Integer
    • A JAJL data type that can be set to a non-decimal value.
  • Float
    • A JAJL data type that can be set to a decimal value.

Default memory addresses

Some memory addresses have default values. These are important to implement exactly as specified.

Helper Addresses

These serve no purpose in the language, but can be helpful at times.

  • 0000: 0
  • 000a: 65536
  • 000b: -65536

Addresses Used By Instructions

  • 00ab: 1
  • aaaa: 65
  • ff0a: 0
  • ff1a: 0

Data Types

There are a few data types to implement.

Unallocated

An empty value.

Integer

Can have values from -65536 to 65536. NOTE: In previous implementations, signed integers existed, but these have been removed as of spec v1.2.

Float

Can have values from -65536.0 65536.0.

Function

See section on functions.

Instructions

Initialisation and Destruction

The following is a comprehensive instruction list, which includes basic pesudocode examples for the programmatically minded.

int <memory address>

The int instruction creates an integer at a specific memory address.

Pseudocode
Check if the memory address is valid and unallocated;
If it is:
 Create an integer (value 0) at that memory address.
Otherwise: Throw an error.

flt <memory address>

The flt instruction creates a float at a specific memory address.

Pseudocode
Check if the memory address is valid and unallocated;
If it is:
 Create a float (value 0.0) at that memory address.
Otherwise: Throw an error.

del <memory address>

Deletes a memory address.

Pseudocode
Check if the memory address is valid and allocated;
If it is:
 Make the memory address unallocated;
Otherwise: Throw an error.

Incrementing/Decrementing

inc <memory address>

Increments an integer or float by 1 or 1.0 respectively.

Pseudocode
Check if the memory address is valid and allocated as an Integer/Float;
If it is:
 Get the value of the memory address;
 Set it to the value of the memory address plus one;
Otherwise: Throw an error.

dec <memory address>

Decrements an integer or float by 1 or 1.0 respectively.

Pseudocode
Check if the memory address is valid and allocated as an Integer/Float;
If it is:
 Get the value of the memory address;
 Set it to the value of the memory address minus one;
Otherwise: Throw an error.

incb <memory address>

This command increments a memory address by the value of the 00ab memory address.

Pseudocode
Check if the memory address is valid and allocated as an Integer/Float;
If it is:
 Get the value of the memory address;
 Get the value of the 00ab memory address;
 Check that both are the same type;
 If they are:
 Set the value of the memory address to the value of the 00ab memory address plus the value of the memory address;
 Otherwise: Throw an error.
Otherwise: Throw an error.

decb <memory address>

This command decrements a memory address by the value of the 00ab memory address.

Pseudocode
Check if the memory address is valid and allocated as an Integer/Float;
If it is:
 Get the value of the memory address;
 Get the value of the 00ab memory address;
 Check that both are the same type;
 If they are:
 Set the value of the memory address to the value of the 00ab memory address minus the value of the memory address;
 Otherwise: Throw an error.
Otherwise: Throw an error.

String Buffer

sbfr

Appends a single ASCII character to the string buffer.

Pseudocode
Get the value of the aaaa memory address;
Convert it into an ASCII character;
Append that ASCII character to the string buffer;

prnt

Prints the contents of the string buffer.

Pseudocode
Print the string buffer;

sclr

Clears the string buffer.

Pseudocode
Set the string buffer to an empty value.

Stack

push <memory address>

Increments the value of the stack to a memory address.

Pseudocode
Check if the memory address is valid and allocated as an Integer;
If it is:
 Get the value of the memory address;
 Increment the value of the stack by the value of the memory address;
Otherwise: Throw an error.

pop <memory address>

Increments the value of a memory address as the value of the stack.

Pseudocode
Check if the memory address is valid and allocated as an Integer;
If it is:
 Get the value of the stack;
 Increment the value of the memory address by the value of the stack;
Otherwise: Throw an error.

copy <memory address>

Sets the value of the stack to the value of a memory address. Different from PUSH, which increments.

Pseudocode
Check if the memory address is valid and allocated as an Integer;
If it is:
 Get the value of the memory address;
 Set the value of the stack to that value;
Otherwise: Throw an error.

pste <memory address>

Sets the value of a memory address to the value of the stack.

Pseudocode
Check if the memory address is valid and allocated as an Integer;
If it is:
 Get the value of the stack;
 Set the value of the memory address by the value of the stack.
Otherwise: Throw an error.

rstk

Sets the stack to a blank integer.

Pseudocode
Set the value of the stack to 0;

Pointer

pnt <memory address>

Sets the pointer.

Pseudocode
Check if the memory address is valid and allocated;
If it is:
 Set the pointer to the memory address; 
Otherwise: Throw an error.

free

NOTE: This instruction is optional.

Sets the pointer to the first UNALLOCATED memory address in the address space.

Pseudocode
For each memory address in address space:
 Check if the memory address is allocated;
 If it is:
 Set the pointer to that memory address;
 Stop searching through memory addresses;

Debugging

dump

This command displays every single allocated memory's address, value, and data type. The exact formatting is not specified, however, a compliant implementation does require that all three are shown. While not required, all should be shown on one line as well.

Pseudocode
For each memory address in address space:
 Check if the memory address is allocated;
 If it is:
 Print its address, value, and data type;
 Continue searching through memory addresses;

glvw

This command lists all global variables.

Pseudocode
For each memory address in global scope:
 Prints its address;
 Continue iterating through addresses;

Arithmetic

add <memory address>

Performs the operation ff0a + ff1a and saves the result to the specified memory address.

Pseudocode
If the memory address is valid and allocated as a float:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Perform the operation <value of ff0a> + <value of ff1a>;
 Save the result of the above operation to the memory address;
 Otherwise: Throw an error.
Otherwise: Throw an error.

sub <memory address>

Performs the operation ff0a - ff1a and saves the result to the specified memory address.

Pseudocode
If the memory address is valid and allocated as a float:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Perform the operation <value of ff0a> - <value of ff1a>;
 Save the result of the above operation to the memory address;
 Otherwise: Throw an error.
Otherwise: Throw an error.

mul <memory address>

Performs the operation ff0a * ff1a and saves the result to the specified memory address.

Pseudocode
If the memory address is valid and allocated as a float:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Perform the operation <value of ff0a> * <value of ff1a>;
 Save the result of the above operation to the memory address;
 Otherwise: Throw an error.
Otherwise: Throw an error.

div <memory address>

Performs the operation ff0a / ff1a and saves the result to the specified memory address.

Pseudocode
If the memory address is valid and allocated as a float:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Perform the operation <value of ff0a> + <value of ff1a>;
 Save the result of the above operation to the memory address;
 Otherwise: Throw an error.
Otherwise: Throw an error.

cast <memory address>

Converts an Integer to a Float, and vice versa.

Pseudocode
Check if the memory address is valid an allocated as an Integer or Float;
If it's an Integer:
 Cast the value of the memory address into a float;
 Set the data type of the memory address to a Float;
If it's a Float:
 Cast the value of the memory address into an integer;
 Set the data type of the memory address to an Integer;
Otherwise: Throw an error.

Logical Operators

gt <memory address>

Checks if the value of ff0a is greater than the value of ff1a, and saves the result to the specified memory address, where 0 is true and 1 is false.

Pseudocode
Check if the memory address is valid and allocated as an integer;
If it is:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Check if the ff0a value is greater than the value of ff1a;
 If it is:
 Set the value of the specified memory address to 0;
 Otherwise: Set it to 1.
Otherwise: Throw an error.

lt <memory address>

Checks if the value of ff0a is lesser than the value of ff1a, and saves the result to the specified memory address, where 0 is true and 1 is false.

Pseudocode
Check if the memory address is valid and allocated as an integer;
If it is:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Check if the ff0a value is lesser than the value of ff1a;
 If it is:
 Set the value of the specified memory address to 0;
 Otherwise: Set it to 1.
Otherwise: Throw an error.

eq <memory address>

Checks if the value of ff0a is equal to the value of ff1a, and saves the result to the specified memory address, where 0 is true and 1 is false.

Pseudocode
Check if the memory address is valid and allocated as an integer;
If it is:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Check if the ff0a value is equal to the value of ff1a;
 If it is:
 Set the value of the specified memory address to 0;
 Otherwise: Set it to 1.
Otherwise: Throw an error.

neq <memory address>

Checks if the value of ff0a is not equal to the value of ff1a, and saves the result to the specified memory address, where 0 is true and 1 is false.

Pseudocode
Check if the memory address is valid and allocated as an integer;
If it is:
 Get the value of address ff0a;
 Get the value of address ff1a;
 
 Check if the ff My files doesn't even have an input templates just a saved games file, am I missing something?0a value is not equal to the value of ff1a;
 If it is:
 Set the value of the specified memory address to 0;
 Otherwise: Set it to 1.
Otherwise: Throw an error.

jmpz <memory address>

The classic jump-if-zero instruction. If the value of the specified memory address is 0, it runs the function defined by the pointer.

Pseudocode
Check if the memory address is valid and allocated as an integer;
If it is:
 Check if the value of the memory address is 0;
 If it is:
 Check if the pointer is pointing to a valid function;
 If it is:
 Call that function;
 Otherwise: Throw an error;
Otherwise: Throw an error.

Functions

Functions, added in v1.1, are a special data type that hold JAJL code inside of them.

Definitions

Functions are defined like so:

func <memory address>

From this point on, every line after this line is treated as part of the function and is NOT executed, but instead added as a line for the function.

Then, when the line endf is provided, lines are no longer treated as part of the function and the function is allocated.

Calling

A function is called like so:

call <memory address>

Functions cannot take arguments. They store JAJL code that is executed when they are called.

Functions also inherit all memory addresses marked as being global (see below section on scope).

Function 'Returns'

When a function's address space is defined, the value of ffff is set to a blank integer.

Once a function finishes executing, the value of ffff is read. If it has changed, set the top-level value of ffff to that value.

Other Nuances

  • While the official implementation allows for recursive functions, it is non-standard behaviour and a side effect of how the interpreter was designed. Dialects should not be expected to provide functions within functions.

Scope

Each function has its own address space, meaning a value created in the main function is not visible inside a function, unless it is marked as global. If this happens, initialised functions will inherit a copy of all global variables.