free software resistance

 the cost of computing freedom is eternal vigilance

### fig-os-prototype-03 *originally posted:* nov 2024 this program is a prototype reference implementation for a language similar to fig. version 3 adds some more helpful error messages and fixes mores issues, including parsing command separators out of strings which- of course, the parser was designed specifically to avoid- but you have to actually write the else conditions, its not enough to just plan to do those. this is version 3 in the same 24 hours, and ive never written a half-decent repl before and i feel pretty happy with it so far, but that doesnt make funny unintentional errors (even easy to fix ones) less funny. ``` #!/usr/bin/env pypy2 # coding: utf-8 # 2015-2024 by mn # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. proginf = "fig os prototype 0.3, nov 2024 mn" # this is a repl implementation of a dialect based on fig. # while it should become practical to use for something, # the actual purpose is a reference implementation prototype # for fig os, which would not be python-based. import sys import os from sys import stdin, stdout from os import popen as figpo from os import system as figsh def printerr(p, f, e, b): now = figcolourtext(0, e) now = fighighlight(0, b) print " " + p now = figcolourtext(0, f) def figindentcode(p, indent): return chr(32) * figatleast(0, indent) + p def bufproc(cbuf, cvar, vars, userfuncs, indent): if len(cbuf) == 1: if cbuf[0].lower() == "next": cout = "" #if figatleast(0, indent - 4): cout = [cout] print "cout NEXT", indent return cout if len(cbuf[0]): if cbuf[0][0] in ".1234567890-": cout = figindentcode(cvar + " = " + cbuf[0], indent) print "cout", cout return cout if cbuf[0][0] == chr(34): cout = figindentcode(cvar + " = " + cbuf[0], indent) print "cout", cout return cout if cbuf[0].lower() == "print": cout = figindentcode("print(" + cvar + ")", indent) print "cout", cout return cout if cbuf[0].lower() == "shell": cout = figindentcode("figshell(" + cvar + ")", indent) print "cout", cout return cout if cbuf[0].lower() == "arrshell": cout = figindentcode(cvar + " = figarrshell(" + cvar + ")", indent) print "cout", cout return cout if cbuf[0].lower() == "getvars": cout = figindentcode(cvar + " = " + chr(34) + "['" + "', '".join(vars) + "']" + chr(34), indent) if indent: cout = [cout] print "cout", cout return cout if len(cbuf) == 2: if cbuf[0].lower() == "forin": if cbuf[1].lower() in vars: cbuf[1] = cbuf[1].lower() cout = figindentcode("for " + cvar + " in " + cbuf[1] + ":", indent) print "cout", cout return cout if len(cbuf) == 2: if cbuf[0].lower() == "get": cbuf[1] = cbuf[1].lower() cout = figindentcode(cvar + " = " + cbuf[1], indent) print "cout", cout return cout if cbuf[0].lower() == "divby": if cbuf[1].lower() in vars: cbuf[1] = cbuf[1].lower() cout = figindentcode(cvar + " = figdivby(" + cvar + ", " + cbuf[1] + ")", indent) print "cout", cout return cout cout = chr(32) * figatleast(0, indent) print cout return cout def figatleast(s, p): if p < s: return s else: return p def figdivby(p, s): p = float(p) / s if p == float(int(p)): p = int(p) return p def figarrshell(c): global figsysteme try: figsysteme = 0 sh = figpo(c) ps = sh.read().replace(chr(13) + chr(10), chr(10)).replace(chr(13), chr(10)).split(chr(10)) figsysteme = sh.close() except: print "error running arrshell command: " + chr(34) + str(c) + chr(34) figend(1) return ps[:] def figsgn(p): p = float(p) if p > 0: return 1 if p < 0: return -1 return 0 def figstr(p): return str(p) def figprint(p): print p def figchr(p): if type(p) == str: if len(p) > 0: return p[0] return chr(p) def figprints(p): stdout.write(str(p)) sys.stdout.flush() def figleft(p, s): return p[:s] def figmid(p, s, x): arr = 0 if type(p) == list or type(p) == tuple: arr = 1 rt = p[s - 1: x + s - 1] if arr and len(rt) == 1: rt = rt[0] return rt def figright(p, s): return p[-s:] def figlcase(p): return p.lower() def figucase(p): return p.upper() def figint(p): return int(p) def figarrset(x, p, s): if type(s) == tuple: if len(s) == 1: fas = s[0] elif type(s) == list: if len(s) == 1: fas = s[0] else: fas = s x[p - 1] = s def figcls(x): if figosname == "nt": cls = figsh("cls") else: stdout.write("\x1b[2J\x1b[1;1H") sys.stdout.flush() def figarropen(x, s): p = open(s) f = p.read().replace(chr(13) + chr(10), chr(10)).replace(chr(13), chr(10)).split(chr(10)) p.close() return f[:] def figarrcurl(x, s): from urllib import urlopen x = str(urlopen(s).read()) x = x.replace(chr(13) + chr(10), chr(10)).replace(chr(13), chr(10)).split(chr(10)) return x[:] def figarrstdin(x): ps = [] for p in stdin: ps += [p[:-1]] return ps[:] def figarrget(x, p, s): if 1: return p[s - 1] def figplus(p, s): if type(p) in (float, int): if type(s) in (float, int): p = p + s else: p = p + s # float(s) if you want it easier if p == float(int(p)): p = int(p) else: if type(p) == str: p = p + s # str(s) if you want it easier if type(p) == list: if type(s) == tuple: p = p + list(s) elif type(s) == list: p = p + s[:] else: p = p + [s] if type(p) == tuple: if type(s) == tuple: p = tuple(list(p) + list(s)) elif type(s) == list: p = tuple(list(p) + s[:]) else: p = tuple(list(p) + [s]) return p def figjoin(p, x, s): t = "" if len(x): t = str(x[0]) for c in range(len(x)): if c > 0: t += str(s) + str(x[c]) return t # s.join(x) def figarr(p): if type(p) in (float, int, str): p = [p] else: p = list(p) return p def figsplit(p, x, s): return x.split(s) def figval(n): n = float(n) if float(int(n)) == float(n): n = int(n) return n def figtimes(p, s): if type(p) in (float, int): p = p * s # float(s) if you want it easier if p == float(int(p)): p = int(p) else: if type(p) == list: p = p[:] * s # figval(s) else: p = p * s # figval(s) if you want it easer return p def figdivby(p, s): p = float(p) / s if p == float(int(p)): p = int(p) return p def figminus(p, s): return p - s def figtopwr(p, s): p = p ** s if p == float(int(p)): p = int(p) return p def figmod(p, s): return p % s def figsqr(p): from math import sqrt p = sqrt(p) if p == float(int(p)): p = int(p) return p def figlineinput(p): return raw_input() def figlen(p): return len(p) def figasc(p): return ord(p[0]) def figend(x): quit() def figsystem(x): quit() def figcolortext(x, f): b = 0 if f == None: f = 0 if b == None: b = 0 n = "0" if f > 7: n = "1" f = f - 8 if f == 1: f = 4 ## switch ansi colours for qb colours elif f == 4: f = 1 ## 1 = blue not red, 4 = red not blue, etc. if f == 3: f = 6 elif f == 6: f = 3 if b > 7: b = b - 8 if b == 1: b = 4 elif b == 4: b = 1 if b == 3: b = 6 elif b == 6: b = 3 stdout.write("\x1b[" + n + ";" + str(30+f) + "m") return "\\x1b[" + n + ";" + str(30+f) + ";" + str(40+b) + "m" def figcolourtext(x, f): global figcgapal global figcgapalcopy f24 = f b = 0 if f == None: f = 0 if b == None: b = 0 n = "0" if f > 7: n = "1" f = f - 8 if f == 1: f = 4 ## switch ansi colours for qb colours elif f == 4: f = 1 ## 1 = blue not red, 4 = red not blue, etc. if f == 3: f = 6 elif f == 6: f = 3 if b > 7: b = b - 8 if b == 1: b = 4 elif b == 4: b = 1 if b == 3: b = 6 elif b == 6: b = 3 if figcgapal == figcgapalcopy: stdout.write("\x1b[" + n + ";" + str(30+f) + "m") return "\x1b[" + n + ";" + str(30+f) + ";" + str(40+b) + "m" else: stdout.write("\x1b[38;2;" + str(figcgapal[f24][0]) + ";" + str(figcgapal[f24][1]) + ";" + str(figcgapal[f24][2]) + "m") return "\x1b[" + n + ";" + str(30+f) + ";" + str(40+b) + "m" figcgapal = [(0, 0, 0), (0, 0, 170), (0, 170, 0), (0, 170, 170), (170, 0, 0), (170, 0, 170), (170, 85, 0), (170, 170, 170), (85, 85, 85), (85, 85, 255), (85, 255, 85), (85, 255, 255), (255, 85, 85), (255, 85, 255), (255, 255, 85), (255, 255, 255)] figcgapalcopy = figcgapal[:] # support 24bit colour hack def figget(p, s): return s def fighighlight(x, b): f = None if f == None: f = 0 if b == None: b = 0 n = "0" if f > 7: n = "1" f = f - 8 if f == 1: f = 4 ## switch ansi colours for qb colours elif f == 4: f = 1 ## 1 = blue not red, 4 = red not blue, etc. if f == 3: f = 6 elif f == 6: f = 3 if b > 7: b = b - 8 if b == 1: b = 4 elif b == 4: b = 1 if b == 3: b = 6 elif b == 6: b = 3 stdout.write("\x1b[" + n + str(40+b) + "m") return "\x1b[" + n + str(40+b) + "m" def figinstr(x, p, e): try: return p.index(e) + 1 except: return 0 def figchdir(p): try: figoch(p) except: print "no such file or directory: " + str(p) figend(1) def figshell(p): global figsysteme try: figsysteme = figsh(p) except: print "error running shell command: " + chr(34) + str(p) + chr(34) figend(1) def figarrshell(c): global figsysteme try: figsysteme = 0 sh = figpo(c) ps = sh.read().replace(chr(13) + chr(10), chr(10)).replace(chr(13), chr(10)).split(chr(10)) figsysteme = sh.close() except: print "error running arrshell command: " + chr(34) + str(c) + chr(34) figend(1) return ps[:] def figprocline(cln): tokenbuf = [] stbuf = "" inq = 0 cmt = 0 for each in cln.lstrip(): if each == chr(34): if inq: inq = 0 tokenbuf += [stbuf + chr(34)] stbuf = "" else: inq = 1 stbuf += chr(34) elif each == "#": if inq == 0: cmt = 1 if stbuf == "": return tokenbuf else: if stbuf.rstrip() != "": stbuf += "#" elif each == "|": if inq == 0: if cmt == 0: if stbuf != "": tokenbuf += [stbuf] tokenbuf += ["|"] stbuf = "" else: if stbuf.rstrip() != "": stbuf += "|" elif each == ";": if inq == 0: if cmt == 0: if stbuf != "": tokenbuf += [stbuf] tokenbuf += [";"] stbuf = "" else: if stbuf.rstrip() != "": stbuf += ";" elif each == "=": if inq == 0: if cmt == 0: if stbuf != "": tokenbuf += [stbuf] tokenbuf += ["="] stbuf = "" else: if stbuf.rstrip() != "": stbuf += "=" elif each == " ": if inq == 0: if stbuf.rstrip() != "": tokenbuf += [stbuf] stbuf = "" else: if stbuf.rstrip() != "": stbuf += " " else: if cmt == 0: stbuf += each if stbuf.rstrip() != "": tokenbuf += [stbuf] return tokenbuf res = ["lineinput", "next", "system", "exit", "forin", "iftrue", "next", "divby", "getvars", "get", "shell"] vars = [] userfuncs = [] pline = [] cvar = "base" base = 0 indent = 0 ecbuf = [] while 1: now = figcolourtext(0, 7) now = fighighlight(0, 0) figprompt = "[" * figatleast(int(indent / 4), 0) if not figprompt: figprompt = "]" figprints(figprompt + " ") cln = figlineinput(0) if not indent: bufml = [] haltp = 0 rec = 0 tc = cln.strip().split(" ") if len(tc): pline = figprocline(cln) print pline if len(pline): rec = 1 if not pline[0].lower() in res: try: exec(pline[0].lower() + " = 0") cvar = pline[0].lower() bufml = [pline[0].lower()] print "cvar:", cvar if not pline[0].lower() in res + vars: vars += [pline[0].lower()] except: printerr("unable to set variable:", 7, 3, 0) print "", pline[0] print haltp = 1 else: pline = ["|"] + pline linebuf = pline[1:] + ["|"] cbuf = [] if linebuf != ["|"] and haltp == 0: print linebuf bufpoint = 0 while haltp == 0: each = linebuf[bufpoint] if each in ['|', ';', '=']: linebuf = linebuf[len(cbuf) + 1:] if cbuf: # print "full command:", cbuf ecmd = bufproc(cbuf, cvar, vars, userfuncs, indent) bufml += cbuf if cbuf[0].lower() in ["next"]: indent = figatleast(0, indent - 4) if cbuf[0].lower() in ["forin", "iftrue"]: indent = figatleast(0, indent + 4) if indent > 0: ecbuf += [ecmd] print "ecbuf:", ecbuf if indent == 0: figml = chr(10).join(ecbuf + [ecmd]) ecbuf = [] print "figml:" + chr(10) + figml try: exec(figml) except ZeroDivisionError: printerr("division by zero:", 7, 3, 0) print "", " -> ".join(bufml) print haltp = 1 except SyntaxError: printerr("command not used correctly", 7, 3, 0) print "", " -> ".join(bufml) print haltp = 1 except NameError: printerr("unset variable referenced:", 7, 3, 0) unrefvars = [] for each in bufml: if each.lower() not in vars and each.lower() not in res and each[0].lower() in "qazwsxedcrfvtgbyhnujmikolp": unrefvars += [each] print "", ", ".join(unrefvars) print haltp = 1 cbuf = [] bufpoint = 0 else: cbuf += [each] bufpoint += 1 if bufpoint >= len(linebuf): break if cln.lower().strip() in ["system", "exit"]: print break if rec == 0: now = figcolourtext(0, 3) printerr("command not recognised or used correctly", 7, 3, 0) print ``` license: 0-clause bsd ``` # 2018, 2019, 2020, 2021, 2022, 2023, 2024 # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ``` => https://freesoftwareresistance.neocities.org