DefLang
DefLang is designed by PSTF.
It is derived from Brainfuck.
Specification
DefLang program consist a header and a script, where:
- Header contains all the command you designed, and
- Script is the main program.
Syntax
To define a command, you use this syntax: command_character@«argument_list» = implementation
The blue part will be implemented in future.
Command character can be ANY character that is not a built-in commands. This is the built-in command table:
Command | Description |
---|---|
>
|
Move the pointer to the right |
<
|
Move the pointer to the left |
+
|
Increment the memory cell at the pointer |
-
|
Decrement the memory cell at the pointer |
.
|
Output the character signified by the cell at the pointer |
,
|
Input a character and store it in the cell at the pointer |
[
|
Jump past the matching ] if the cell at the pointer is 0
|
]
|
Jump back to the matching [ if the cell at the pointer is nonzero
|
{
|
Jump past the matching } anyway, ignore everything in it
|
}
|
Does nothing |
(
|
Jump past the matching ) if the cell at the pointer is 0
|
)
|
Does nothing |
:
|
Output the current cell data directly in decimal |
;
|
Input a decimal ending by a blank character and store it in the cell at the pointer |
$
|
Does nothing, or as a command seperator |
@
|
Switch from the tape to accumulator or back |
*
|
Multiply the current cell with accumulator |
`
|
Divide the current cell by accumulator, and is rounded toward 0 |
%
|
Divide the current cell by accumulator, and results in remainder |
/
|
Assign accumulator with current cell |
\
|
Assign current cell with accumulator |
Command expansion
The max expansion depth of command should stated in YOUR interpreter, and I recommend you to use a value between 1000 to 10000. If the current expansion depth is over the limit, then a Runtime Error is throwed out. This is to prevent from Infinity Recursion.
Execution
The infinite tape and the accumulator is first initialized to 0. Input is read from STDIN, and output is wrote to STDOUT.
Note
The current interpreter does not support instructions with arguments.
Interpreter in Python
from collections import defaultdict def run_deflang(program, input_str=""): # Split into header and script header, _, script = program.partition("_________") # Parse header definitions defs = {} for line in header.splitlines(): line = line.strip() if not line or '=' not in line: continue cmd, _, impl = line.partition('=') cmd = cmd.strip() impl = impl.strip() if len(cmd) == 1: defs[cmd] = impl # Expand script recursively expanded = expand_commands(script, defs) # Run as Brainfuck run_brainfuck(expanded, input_str) MAX_DEPTH = 1000 def expand_commands(s, defs, depth=0): if depth > MAX_DEPTH: raise RuntimeError("Max recursion depth exceeded") res = [] for c in s: if c in defs: res.append(expand_commands(defs[c], defs, depth + 1)) else: res.append(c) return ''.join(res) def run_brainfuck(code, input_str): tape = defaultdict(int) ptr = 0 acc = 0 pc = 0 type = 0 input_index = 0 loop_map = build_loop_map(code) cond_map = build_cond_map(code) comment_map = build_comment_map(code) while pc < len(code): c = code[pc] if c == '>': ptr += 1 elif c == '<': ptr -= 1 elif c == '+': if type == 0: tape[ptr] = (tape[ptr] + 1) else: acc += 1 elif c == '-': if type == 0: tape[ptr] = (tape[ptr] - 1) else: acc -= 1 elif c == '@': type = (type + 1) % 2 elif c == '.': print(chr(tape[ptr]), end='') elif c == ',': tape[ptr] = ord(input_str[input_index]) if input_index < len(input_str) else 0 input_index += 1 elif c == '[' and tape[ptr] == 0: pc = loop_map[pc] elif c == ']' and tape[ptr] != 0: pc = loop_map[pc] elif c == '(' and tape[ptr] == 0: pc = cond_map[pc] elif c == ')': pass elif c == '{': pc = comment_map[pc] elif c == '}': pass elif c == '$': pass elif c == '*': tape[ptr] = (tape[ptr] * acc) elif c == '`': tape[ptr] = (tape[ptr] // acc) elif c == '%': tape[ptr] = (tape[ptr] // acc) elif c == '\': tape[ptr] = acc elif c == '/': acc = tape[ptr] pc += 1 def build_loop_map(code): stack = [] loop_map = {} for i, c in enumerate(code): if c == '[': stack.append(i) elif c == ']': start = stack.pop() loop_map[start] = i loop_map[i] = start if stack: raise SyntaxError("Unmatched brackets") return loop_map def build_cond_map(code): stack2 = [] cond_map = {} for i, c in enumerate(code): if c == '(': stack2.append(i) elif c == ')': start = stack2.pop() cond_map[start] = i cond_map[i] = start if stack2: raise SyntaxError("Unmatched brackets") return cond_map def build_com_map(code): stack3 = [] comment_map = {} for i, c in enumerate(code): if c == '{': stack3.append(i) elif c == '}': start = stack3.pop() comment_map[start] = i comment_map[i] = start if stack3: raise SyntaxError("Unmatched brackets") return comment_map
Example
Hello, World!
0 = [-] A = ++++++++[>++++++++<-]> ~ = ++++[>++++++++<-]> ! = ~+ C = ~++++++++++++ a = ++++++++[>++++++++++++<-]> _________ A++++++++.0<0a+++++.0<0a++++++++++++..+++.0<0C0<0~0<0 A+++++++++++++++++++++++.0<0a+++++++++++++++.+++.------.--------.0<0!.0<0