MovLang

From Esolang
Jump to navigation Jump to search

MovLang
Paradigm(s) imperative
Designed by Sulphuris
Appeared in 2024
Memory system Cell-based
Dimensions one-dimensional
Computational class Turing complete
Reference implementation Movlang JBC compiler
Influenced by Assembly, Movfuscator (not a language)
File extension(s) .movl

Language overview

A simple language that consists of a single instruction: copy memory (MOV)

Syntax

[<label>:]
<dest> <value>[size]

where:
dest is a desination address where to put the value;
value is the value to put;
size is an optional hint for the compiler how much memory should be taken.

Dereferensing:

<segment>'['<value>[+<offset>|<bit_offset>]']'

Like breaks doesn't matter and play the same role as whitespace

Size specifier:

:<size_in_bytes|^size_in_bits>

Preprocessor

To make this language less painful to use, it provides a macroprocessor that allows users to somewhat customize the language syntax.
The preprocessor supports following directives:

#def

#def <alias> <name>

Defines an alias for a single token.
Examples:

#def stdout C

// now every token with text "stdout" will be replaced with "C"

stdout[00] 'H' // C[00] 'H'
stdout[01] 'e' // C[01] 'e'
#def inc_table 00A0
0[inc_table + 0] 1 // 0[00A0 + 0] 1
0[inc_table + 1] 2 // 0[00A0 + 1] 2

#include

#include <filename>

Includes all the file content ("file.movl" = file).

#macro

#macro <name> [#args#{}[]<>] 
#unfolds [content] 
#end_macro

Creates a macro with a custom syntax.
Examples:

#macro inc #seg#[#addr#]
#unfolds
#seg#[#addr#] 0[inc_table + #seg#[#addr#]]
#end_macro

A[00] 1
inc A[00] // now A[00] = 2
#macro
invoke2 #name#(#arg1#, #arg2#) : #argsize#
#unfolds
#def Label #uniq

S[E[08] + 0C] @!Label
S[E[0C] + 10] #arg1# :#argsize#
S[E[0C] + 10 + #argsize#] #arg2# :#argsize#
E[00] #name#
Label:

#undef Label
#end_macro
#macro swap #seg1#[#addr1#] <-#size#-> #seg2#[#addr2#]
#unfolds
0[600] #seg1#[#addr1#] : #size#
#seg1#[#addr1#] #seg2#[#addr2#] : #size#:
#seg2#[#addr2#] 0[600] : #size#:
#end_macro

swap F[0E] <-8-> F[00] // swap 8 bytes in F[0E] and F[00]

#segment

#segment <name> <size>

Specifies the segment size.
Example:

#segment F FA0 // now sizeof segment F = 4000 bytes

#rule

#rule <rule> <value>

Set a rule for a compiler.
Rules:

  1. default_seg_size - default segment size (default = `FFFF`, max = `FFFFFFFF`)
  2. address_size - address size (default = `4`, available values: `1`, `2`, `4`, `8`)
  3. implicit_seg - if 0, you can only use segments that you explicitly specified with `#segment` (default = `1`, available values = `0`, `1`)

#filename

#filename

Will be replaced with name of current file (without extension).

#line

#line

Will be replaced with number of current line.

#time

#time

Will be replaced with program compilation time (with :8 as object size).

#uniq

#uniq

Will be replaced with unique hex value (with :8 as object size).

#embed

#embed <segment>'['<base_address>']' <filename>

Writes a file byte by byte to the specified address.
Example:

// hello.txt
Hello World

// program.movl
#embed C[0] "hello.txt"
// will be converted to
C[0+0] 'H'
C[0+1] 'e'
C[0+2] 'l'
C[0+3] 'l'
C[0+4] 'o'
C[0+5] ' '
C[0+6] 'W'
C[0+7] 'o'
C[0+8] 'r'
C[0+9] 'l'
C[0+A] 'd'