Newer
Older
NewLang / main.py
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# Copyright 2021 Jookia <contact@jookia.org>

import log
import parse

def text_create(value):
    return ("text", value)
def text_value(object):
    return object[1]
def text_dispatch(object, verb, args):
    value = text_value(object)
    if verb == "Append":
        appendix = text_value(args[0])
        return text_create(value + " " + appendix)
    return None

def module_create(verbs):
    return ("module", verbs)
def module_dispatch(object, verb, args):
    (type, functions) = object
    return functions[verb](object, args)

def do_system_print(subject, args):
    print(text_value(args[0]))
    return None
def do_system_read(subject, args):
    return text_create(input())
system_module = module_create({
    "Print": do_system_print,
    "Read": do_system_read,
})

def resolve_value(env, value):
    (type, value) = value
    if type == "reference":
        return env[value]
    elif type == "text":
        return text_create(value)
    else:
        print("Unimplemented value type: %s" % (type))

def run_statement(env, ast):
    subject = resolve_value(env, ast[1])
    verb = ast[2]
    if verb == None:
        return subject
    args = []
    for arg in ast[3]:
        args.append(resolve_value(env, arg))
    if subject[0] == "text":
        return text_dispatch(subject, verb, args)
    elif subject[0] == "module":
        return module_dispatch(subject, verb, args)
    return None

def run_set(env, ast):
    env[ast[1]] = run_statement(env, ast[2])
    return env[ast[1]]

def run_if(env, ast):
    print("Unimplemented if")
    return None

def run_command(env, ast):
    type = ast[0]
    if type == "statement":
        return run_statement(env, ast)
    elif type == "set":
        return run_set(env, ast)
    elif type == "if":
        return run_if(env, ast)
    else:
        print("Unknown command type %s" % (ast))
        return None

def main(args):
    if len(args) != 2:
        print("Usage: main.py FILENAME")
        return 1
    log.set_default_log_level()
    filename = args[1]
    code = open(filename).read()
    if code[0:2] == '#!':
        next_line = code.find('\n') + 1
        code = code[next_line:]
    ast = parse.parse_file(code)
    if not ast:
        return 1
    env = {
        "System": system_module,
    }
    for command in ast:
        run_command(env, command)
    return 0

if __name__ == "__main__":
    import sys
    sys.exit(main(sys.argv))