diff --git a/uxnbot.py b/uxnbot.py new file mode 100644 index 0000000..a919d83 --- /dev/null +++ b/uxnbot.py @@ -0,0 +1,81 @@ +#!/usr/bin/python + +import re +import socket +import sys +import tempfile +import uxnrepl + +server = "irc.libera.chat" +nick = b"uxnbot" +channel = b"#uxnbot" + +sandbox = tempfile.mkdtemp(prefix='uxnrepl') + +irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +def send(msg): + print('>>> %r' % msg) + irc.send(msg + b'\r\n') + +def recv(): + msg = irc.recv(2040) + print('<<< %r' % msg) + return msg + +print("connecting to: %s" % server) + +irc.connect((server, 6667)) +send(b"USER %s %s %s :bot for testing uxntal code" % (nick, nick, nick)) +send(b"NICK %s" % nick) +#send("PRIVMSG nickserv :iNOOPE\r\n") +send(b"JOIN %s" % channel) + +ping_re = re.compile(br'PING (.+)$') +chan_msg_re = re.compile(br':([^!]+)![^ ]+ PRIVMSG ([^ ]+) :' + nick + br': (.*)$') +priv_msg_re = re.compile(br':([^!]+)![^ ]+ PRIVMSG ' + nick + br' :(.*)$') + +ignored = {b'rst', b'wst', b''} + +def evaluate(msg): + output = uxnrepl.execute(msg, sandbox=sandbox) + lines = [s.strip() for s in output.split(b'\n')] + interesting = [s for s in lines if s not in ignored] + result = b' | '.join(interesting) + print('*** executing %r gave %r -> %r -> %r' % (msg, output, interesting, result)) + return result + +while True: + #text = irc.recv(2040) + #print(text) + text = recv() + + m = ping_re.match(text) + if m: + send(b'PONG %s' % m.group(1)) + continue + + m = chan_msg_re.match(text) + if m and m.group(2) == channel: + user = m.group(1) + msg = m.group(3).strip() + result = evaluate(msg) + send(b'PRIVMSG %s :%s: %s' % (channel, user, result)) + continue + + m = priv_msg_re.match(text) + if m: + user = m.group(1) + msg = m.group(2).strip() + result = evaluate(msg) + send(b'PRIVMSG %s :%s' % (user, result)) + continue + +# message from user in channel: +# b':d_m!~d_m@user/d-m/x-5109880 PRIVMSG #uxn :uxnbot: hello\r\n' + +# keep alive: +# b'PING :mercury.libera.chat\r\n' + +# private message +# b':d_m!~d_m@user/d-m/x-5109880 PRIVMSG uxnbot :hello\r\n' diff --git a/uxnrepl b/uxnrepl index a6e7cf5..3eedbe1 100755 --- a/uxnrepl +++ b/uxnrepl @@ -14,7 +14,7 @@ template = ''' @dump-wst #04 DEI #01 GTH ?&next !emit-wst &next STH !dump-wst -@emit-wst +@emit-wst #05 DEI LIT [ &n $1 ] GTH ?&next #0a18 DEO !start-rst &next STHr emit #2018 DEO !emit-wst diff --git a/uxnrepl.py b/uxnrepl.py new file mode 100644 index 0000000..b8733b3 --- /dev/null +++ b/uxnrepl.py @@ -0,0 +1,76 @@ +#!/usr/bin/python + +from os import system +from subprocess import run +from sys import stdin, stdout +from tempfile import mkstemp + +sandbox = None + +template = ''' +|0100 + ( start ) %s ( end ) + + #05 DEI ,emit-wst/n STR + ;wst print + +@dump-wst + #04 DEI #01 GTH ?&next !emit-wst &next STH !dump-wst + +@emit-wst + #05 DEI LIT [ &n $1 ] GTH ?&next #0a18 DEO !start-rst + &next STHr emit #2018 DEO !emit-wst + +@start-rst + ;rst print + +@dump-rst + #05 DEI #00 GTH ?&next !emit-rst &next STHr !dump-rst + +@emit-rst + #04 DEI #01 GTH ?&next #0a18 DEO #800f DEO BRK + &next emit #2018 DEO !emit-rst + +@print ( addr* -> ) + LDAk DUP ?{ POP POP2 JMP2r } #18 DEO INC2 !print + +@emit + DUP #04 SFT ,&ch JSR + &ch #0f AND DUP #09 GTH #27 MUL ADD #30 ADD #18 DEO JMP2r + +@rst "rst 20 00 +@wst "wst 20 00 +''' + +def write_rom(path, s): + f = open(path, 'w') + prog = template % s.decode('utf-8') + f.write(prog) + f.close() + +def execute(s, sandbox=None): + _, tmp_tal = mkstemp(suffix='.tal', prefix='uxnrepl') + _, tmp_rom = mkstemp(suffix='.rom', prefix='uxnrepl') + write_rom(tmp_tal, s) + res = run(['uxnasm', tmp_tal, tmp_rom], cwd=sandbox, capture_output=True) + ##print('*** uxnasm.res is %r' % res) + if res.returncode != 0: + return res.stderr + res = run(['uxncli', tmp_rom], cwd=sandbox, capture_output=True) + ##print('*** uxncli.res is %r' % res) + return res.stdout + +def main(): + print('uxnrepl (ctrl-d to exit)') + while True: + stdout.write('> ') + stdout.flush() + s = stdin.readline() + if not s: + print('bye!') + break + stdout.write(execute(s).decode('utf-8')) + stdout.flush() + +if __name__ == "__main__": + main()