From d2724925d05138e93b0ff5a97a68538d765799d1 Mon Sep 17 00:00:00 2001 From: Alex Shroyer Date: Wed, 7 Aug 2024 17:07:57 -0400 Subject: [PATCH] simplify 'cmp' to... nothing --- proto2/Parser.py | 29 ++++++++++++++--------------- proto2/Semantic.py | 34 ++++++---------------------------- proto2/Test.py | 18 +++++++++--------- 3 files changed, 29 insertions(+), 52 deletions(-) diff --git a/proto2/Parser.py b/proto2/Parser.py index d512e9a..0e3aee4 100644 --- a/proto2/Parser.py +++ b/proto2/Parser.py @@ -2,17 +2,16 @@ from collections import namedtuple Op = namedtuple('Op','name arity') -def repr_ast(s): +def repr_ast(s) -> str: match s: + case '{': return 'λ' + case '(': return '⋯' + # case ('{',(('[',a),b)): return f'(λ ({repr_ast(a)}) {repr_ast(b)})' case str(): return s - case a,None: return repr_ast(a) - case a,(): return repr_ast(a) - case '(',a: return f'(⋯ {repr_ast(a)})' - case '{',a: return f'(λ {repr_ast(a)})' - case 'vec',a: return f'(vec {" ".join(repr_ast(x) for x in a)})' - case str() as a,b: return f'({a} {repr_ast(b)})' if b else a - case tuple()|list(): return " ".join(map(repr_ast,s)) - return repr(s) + case (a,None|()): return repr_ast(a) + case Ast(): return f'({repr_ast(s.n)} {repr_ast(s.c)})' # if s.c else repr_ast(s.n) + case tuple(): return " ".join(map(repr_ast,s)) + return 42 class Ast(namedtuple('Ast','n c',defaults=(None,))): def __repr__(s): return repr_ast(s) @@ -65,7 +64,8 @@ def rp(x:Op):#(r)educe (p)aren, e.g: reduce(OPAREN); rp(s.pop()) def rq(k:Ast):#juxtaposition-based syntax: projection and composition while s and str(s[-1].name) not in OPAREN+ENDEXP: x,a = s.pop() - k = Ast('cmp',(Ast('prj',(Ast(x),d.pop())),k) if a==2 else Ast(Ast(x),k)) + k = Ast((Ast('prj',(Ast(x),d.pop())) if a==2 else Ast(x)), k) + # k = Ast('cmp',(Ast('prj',(Ast(x),d.pop())),k) if a==2 else Ast(Ast(x),k)) d.append(k); debug('rq') def loop(i=0) -> int|None:#return index of error-causing token (if any), else None @@ -96,16 +96,13 @@ def loop(i=0) -> int|None:#return index of error-causing token (if any), else No if i>=z: return c,i,n = t[i],i+1,nn(i); debug(c,'↔',n or 'END') if balance(c): return i - # if type(c)==tuple: d.append(Ast('vec',list(map(Ast,c)))); continue if c in WHITESPACE and n=='/': return if c in WHITESPACE: continue if c in ENDEXP: reduce(OPAREN); pad(n); s.append(Op(';',2)) elif c in OPAREN: c in "({" and s.append(Op(d.pop(),1)); pad(n); s.append(Op(c,2)) elif c in CPAREN: reduce(OPAREN); rp(x:=s.pop()) - if s and s[-1].name=='{' and x.name=='[' and n!='}': - print('rp binary',s,d) - s.append(Op(';',2)) + if s and s[-1].name=='{' and x.name=='[' and n!='}': s.append(Op(';',2)) else: continue elif c in ADVERB: k = Ast(c,d.pop())#bind adverb to whatever @@ -113,7 +110,9 @@ def loop(i=0) -> int|None:#return index of error-causing token (if any), else No if s: debug('adverb') if not noun(str(s[-1].name)): s.append(Op(k,1)) - else: d.append(Ast(s.pop().name)); s.append(Op(k,2)) + else: + d.append(s.pop().name) + s.append(Op(k,2)) else: s.append(Op(k,1)) if s[-1].arity==2: pad(n) elif c in ASSIGN: diff --git a/proto2/Semantic.py b/proto2/Semantic.py index 8ae45f3..f8f2cef 100644 --- a/proto2/Semantic.py +++ b/proto2/Semantic.py @@ -50,45 +50,23 @@ def lamp(a:Ast) -> Ast: case 'prj',(x,y): return Ast('{',(Ast('[',px),Ast(x.n,(y,px)))) case _: return Ast(lamp(a.n),tuple(map(lamp,a.c))) if a.c else Ast(a.n) -def lamc(a:Ast) -> Ast: - '''merge compositions into inner lambda''' - match a.n: - case 'cmp': # exactly 2 children - match a.c[0].n, a.c[1].n: - case '{','{': - b1 = a.c[0].c[1] - args,b2 = a.c[1].c - return Ast('{',args,Ast(b1.n,b1.c[0],b2)) - case b,'{': - args,b2 = a.c[1].c - return Ast('{',args,Ast(a.c[0].n,b2)) - case '{',b: return lamc(Ast('cmp',a.c[0],(lamc(a.c[1])))) - case b,c: return lamc(Ast('cmp',*map(lamc,a.c))) #lamc(a.c[0]),lamc(a.c[1]))) - case _: return Ast(a.n,tuple(map(lamc,a.c))) if a.c else Ast(a.n) - def get_params(a:Ast) -> str: '''get x y z arguments from lambdas''' - print(a) match a: - case None: return '' case ('x'|'y'|'z',None): return a.n case (':'|'::',(b,c)) if b.n in ('x','y','z'): return get_params(c) - case tuple(): print(type(a)); return ''.join(map(get_params,a)) - case (_,b): return ''.join(map(get_params,b)) if b else '' + case str()|None: return '' + case tuple(): return ''.join(map(get_params,a)) + case _: return get_params(a.n)+get_params(a.c) def formalize(a:Ast) -> Ast: '''add formal arguments to lambdas''' - # (λ body) ⇒ args = get_params(body); return (λ (args) formalize(body)) - # (λ ([ args...) body) ⇒ recurse on body match a: case ('{',(body,)): return Ast('{',(Ast('[',get_params(body)), formalize(body))) case ('{',(('[',args),body)): return Ast('{',(Ast('[',args), formalize(body))) - case ('{',seq): - print('seq',seq) - # return Ast('{',(Ast('[',''.join(map(get_params,seq))), formalize(seq))) - return Ast('{',(Ast('[',get_params(seq)), formalize(seq))) - case b,tuple() as c:return Ast(formalize(b),tuple(map(formalize,c))) - case b,c: return Ast(formalize(b),formalize(c)) + case ('{',tuple() as c): return Ast('{',(Ast('[',tuple(map(Ast,get_params(c)))), formalize(c))) + case (b,tuple() as c):return Ast(formalize(b),tuple(map(formalize,c))) + case (b,c): return Ast(formalize(b),formalize(c)) case _: return a def Sema(a:Ast) -> Ast|Val: diff --git a/proto2/Test.py b/proto2/Test.py index 5e7e7ce..c3d6257 100644 --- a/proto2/Test.py +++ b/proto2/Test.py @@ -9,13 +9,13 @@ def test_expr(scan,parse): # projection/composition/application # a+ ⇒ (prj + a) - +- ⇒ (cmp + (prj -)) + +- ⇒ (+ (prj -)) (+)- ⇒ (prj - +) +(-) ⇒ (+ -) a:b ⇒ (: a b) (a:)2 ⇒ (app (prj : a) 2) - (-+:) ⇒ (cmp - (prj +:)) - -+: ⇒ (cmp - (prj +:)) + (-+:) ⇒ (- (prj +:)) + -+: ⇒ (- (prj +:)) a::b ⇒ (:: a b) a:f/y ⇒ (: a (app (/ f) y)) 1 2+ ⇒ (prj + (vec 1 2)) @@ -23,14 +23,14 @@ def test_expr(scan,parse): 1 2+``a ⇒ (+ (vec 1 2) (vec ` `a)) a b 1 2 ⇒ (app a (app b (vec 1 2))) 1 2 a 3 4 ⇒ (app (vec 1 2) (app a (vec 3 4))) - a+- ⇒ (cmp (prj + a) (prj -)) - *a+- ⇒ (cmp * (cmp (prj + a) (prj -))) - +-* ⇒ (cmp + (cmp - (prj *))) + a+- ⇒ ((prj + a) (prj -)) + *a+- ⇒ (* ((prj + a) (prj -))) + +-* ⇒ (+ (- (prj *))) a+; ⇒ (; (prj + a) ∅) - (+-)/y ⇒ (app (/ (cmp + (prj -))) y) + (+-)/y ⇒ (app (/ (+ (prj -))) y) (2+)/y ⇒ (app (/ (prj + 2)) y) - x(+-)/y ⇒ (app (/ (cmp + (prj -))) x y) - x(+-*)/y ⇒ (app (/ (cmp + (cmp - (prj *)))) x y) + x(+-)/y ⇒ (app (/ (+ (prj -))) x y) + x(+-*)/y ⇒ (app (/ (+ (- (prj *)))) x y) x(2+)/y ⇒ (app (/ (prj + 2)) x y) () ⇒ (⋯ ∅) ()/y ⇒ (app (/ (⋯ ∅)) y)