Day 28

A Minimal Programming Language — Expanded Parser

Try it!



Source Code


memory = {}

def run_cmd(words):
    if not words:
        return
    cmd = words[0]
    if cmd == 'set':
        name = words[1]
        raw = words[3]
        try:
            memory[name] = float(raw) if '.' in raw else int(raw)
        except ValueError:
            memory[name] = raw
    elif cmd == 'print':
        name = words[1]
        print(memory[name] if name in memory else f"Error: '{name}' not defined")
    elif cmd == 'add':
        print(memory[words[1]] + memory[words[3]])
    elif cmd == 'subtract':
        print(memory[words[1]] - memory[words[3]])
    elif cmd == 'multiply':
        print(memory[words[1]] * memory[words[3]])
    elif cmd == 'divide':
        b = memory[words[3]]
        if b == 0:
            print("Error: division by zero")
        else:
            print(memory[words[1]] / b)
    elif cmd == 'loop':
        n = int(words[1])
        for _ in range(n):
            run_cmd(words[2:])
    elif cmd == 'ask':
        name = words[1]
        raw = input(f"Enter {name}: ")
        try:
            memory[name] = float(raw) if '.' in raw else int(raw)
        except ValueError:
            memory[name] = raw
    elif cmd == 'if':
        var, op, raw_val = words[1], words[2], words[3]
        a = memory.get(var)
        try:
            b = float(raw_val) if '.' in raw_val else int(raw_val)
        except ValueError:
            b = raw_val
        ops = {'==': a == b, '>': a > b, '<': a < b, '>=': a >= b, '<=': a <= b}
        if ops.get(op, False) and len(words) > 4 and words[4] == 'then':
            run_cmd(words[5:])
    elif cmd == 'func':
        name = words[1]
        then_idx = words.index('then')
        memory[name] = words[then_idx + 1:]
    elif cmd == 'call':
        name = words[1]
        if name in memory and isinstance(memory[name], list):
            run_cmd(memory[name])
        else:
            print(f"Error: '{name}' is not a function")
    else:
        print(f"Unknown command '{cmd}'. Type 'help'.")

while True:
    words = input("> ").split()
    if not words:
        continue
    if words[0] == 'exit':
        break
    elif words[0] == 'help':
        print("...")
    else:
        run_cmd(words)

Description


Context: Day 27 built a minimal REPL with four commands. For Day 28 I wanted the language to feel substantially more capable — not just more operators, but the beginnings of control flow and reusable code.

Challenges: The biggest jump in complexity came from func and call. A function stores a tokenized command as a list in memory and replays it on demand — which means run_cmd had to be a proper recursive function rather than inline logic. loop also required recursion into run_cmd, and if needed careful type coercion so numeric comparisons didn't silently compare a stored int against a string literal.

Result: The language now has all four arithmetic operations, user input, loops, conditionals, and named functions. Example session:

set x to 6
multiply x and x → 36
func greet then print x
loop 3 call greet → 6 (×3)
if x > 5 then print x → 6

Previous Day
Next Day