Posted to tcl by Stu at Tue Jun 04 14:31:43 GMT 2024view pretty
#! /usr/bin/env python
"""pTycl - A variation on Python syntax"""
__cow__ = """Copyright (c) 2024 Stuart Cassoff <stwo@users.sourceforge.net>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
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."""
__author__ = "Stuart Cassoff"
__license__ = __cow__
__copyright__ = __cow__
__version__ = "1.0"
__when__ = "Winter/Spring 2024"
__what__ = "pTycl"
#
# pTycl
#
import re
import sys
import evallers
def ptycl (blob, interp=None) {
out = []
level = 0
indent = " "
caret = True
pblob = preprocess(blob)
scanned = scan(pblob)
for n,line in enumerate(pblob.splitlines()) {
if n in scanned {
o,p1,p2 = scanned[n]
if o == -2 {
continue
}
if o == -3 {
out.append("#" + p1)
continue
}
if o == 1 {
line = p1 + " " + p2 + ":"
out.append(indent * level + do_things_to(line, caret))
} elif o == 0 {
line = p1 + ("" if p2 == "" else " " + p2) + ":"
out.append(indent * (level-1) + do_things_to(line, caret))
}
level += o
continue
}
out.append(indent * level + do_things_to(line, caret).strip())
}
return "\n".join(out)
}
def scan (blob) {
<?pragma lambdas off?>
rup = re.compile(r"^\s*(async\s+def|async\s+for|async\s+with|case|class|def|for|if|match|try|with|while|mef|maf)\s+(.*?)\s*\{\s*$")
rz1 = re.compile(r"^\s*\}\s*(elif|except)\s*(.+?)\s*\{.*$")
rz2 = re.compile(r"^\s*\}\s*(else|finally)\s*\{.*$")
rdn = re.compile(r"^\s*\}\s*(?:#\s*.*?)?\s*$")
rpr = re.compile(r"\<\?" + "pragma" + r"\s*(.*?)\?\>", re.S)
<?pragma lambdas on?>
nobraces = False
elide = False
comment = False
scanned = {}
for n,line in enumerate(blob.splitlines()) {
if (m := rpr.search(line)) {
g = m.group(1).split(" ")
if len(g) == 2 {
if g[0] == "braces" {
if g[1] == "on" {
nobraces = False
scanned[n] = (-2,None,None)
} elif g[1] == "off" {
nobraces = True
scanned[n] = (-2,None,None)
}
} elif g[0] == "elide" {
if g[1] == "on" {
elide = True
scanned[n] = (-2,None,None)
continue
} elif g[1] == "off" {
elide = False
scanned[n] = (-2,None,None)
continue
}
} elif g[0] == "comment" {
if g[1] == "on" {
comment = True
scanned[n] = (-2,None,None)
continue
} elif g[1] == "off" {
comment = False
scanned[n] = (-2,None,None)
continue
}
}
}
}
if nobraces : continue
if elide {
scanned[n] = (-2,None,None)
continue
}
if comment {
scanned[n] = (-3,line,None)
continue
}
if (m := rup.match(line)) {
scanned[n] = (1,m.group(1),m.group(2))
} elif (m := rz1.match(line)) {
scanned[n] = (0,m.group(1),m.group(2))
} elif (m := rz2.match(line)) {
scanned[n] = (0,m.group(1),"")
} elif (m := rdn.match(line)) {
scanned[n] = (-1,"","")
}
}
return scanned
}
def preprocess (blob) {
blob = preprocess_includes (blob)
blob = preprocess_comments (blob)
blob = preprocess_shells (blob)
return blob
}
def preprocess_includes (blob) {
while (blob := do_preprocess_includes(nblob:=blob)) != nblob : pass
return blob
}
def do_preprocess_includes (blob) {
reggy = re.compile(r"\<\?" + "include" + r"\s*(.*?)\?\>", re.S)
if not (m := reggy.search(blob)): return blob
for group in m.groups() {
if (res := file_load(group, nonewline=True))[-1] {
blob = blob[:m.span(0)[0]] + res[0] + blob[m.span(0)[1]:]
}
}
return blob
}
def preprocess_comments (blob, comment="//") {
return "\n".join((line for line in blob.splitlines() if not line.strip().startswith(comment))) if comment in blob else blob
}
def preprocess_shells (blob) {
interp = None
shells = {shell:re.compile(r"\<\?" + shell + r"\s*(.*?)\?\>", re.S) for shell in ('tcl','py','sh')}
for shell,reggy in shells.items() {
if not (m := reggy.search(blob)): continue
if shell == 'tcl' {
if interp is None {
import tkinter
interp = tkinter.Tcl()
}
cargo = interp
} elif shell == 'py' {
cargo = {}
} else {
cargo = None
}
for group in m.groups() {
res,ok = evallers.__dict__['eval_' + shell](group, cargo)
if shell == 'sh' {
res = res.removesuffix("\n")
}
blob = blob[:m.span(0)[0]] + res + blob[m.span(0)[1]:]
}
}
return blob
}
def do_things_to (line, caret=False) {
line = mefalize (line)
line = mafalize (line)
line = lambdada (line)
line = selfetate (line)
if caret: line = djam_karet (line)
return line
}
<?pragma m_fs off?>
def mefalize (line) : return re.sub(r"^mef(\s+.+?\()", r"def\1self, " , line).replace("(self, )", "(self)")
def mafalize (line) : return re.sub(r"^maf(\s+.+?\()", r"async def\1self, " , line).replace("(self, )", "(self)")
<?pragma m_fs on?>
def selfetate (line, fles=None) {
if line == "" or "$" not in line {
return line
}
if fles is None : fles = "self"
if line[0] == "$" {
line = fles + "." + line[1:]
}
for s,r in zip(*[iter((
<?pragma self off?>
" $" , " " + fles + "."
, "\t$" , "\t" + fles + "."
, "($)" , "(" + fles + ")"
, "($," , "(" + fles + ","
, "($" , "(" + fles + "."
, "[$" , "[" + fles + "."
, "{$" , "{" + fles + "."
, ":$" , ":" + fles + "."
, ",$" , "," + fles + "."
<?pragma self on?>
))]*2): line = line.replace(s, r)
return line
}
def djam_karet (line) {
if line == "" or "^" not in line {
return line
}
if line[0] == "^" {
line = "return" + line[1:]
}
for s,r in zip(*[iter((
<?pragma carets off?>
" ^ " , " return "
, "\t^\t" , "\treturn\t"
, " ^\t" , " return\t"
, "\t^ " , "\treturn "
, "#^ " , "#return "
, "#^\t" , "#return\t"
<?pragma carets on?>
))]*2): line = line.replace(s, r)
return line
}
def lambdada (line) {
<?pragma lambdas off?>
reggy = re.compile(r"\|\s*(.*?)\s*\|\s*(.+?)\s*\|")
<?pragma lambdas on?>
if not (m := reggy.search(line)): return line
line = line[:m.span(0)[0]] + "lambda " + ",".join(m.group(1).split()) + ":" + m.group(2) + line[m.span(0)[1]:]
return line
}
def main () {
print(ptycl(sys.stdin.read()))
}
if __name__=="__main__":main()
# EOF