"""Independent literal/token arithmetic. Never imports or runs application code.""" from pathlib import Path import hashlib,json ID=lambda n:f'00000000-0000-0000-0000-{n:012}' def rich(sa=False): prop,work,layer,extra=('sa_property','sa_function','layer Sa;',f'sa_system s "System" id "{ID(6)}" {{}}') if sa else ('oa_property','oa_activity','','') main=f'arcadia 8;\nproject p "Project" id "{ID(1)}" {{\ninclude "b.arcadia"; include "a.arcadia";\nnode n id "{ID(4)}" {{ diagram @d; element @v; }}\n{prop} v "Value" id "{ID(3)}" {{ subject @w; type Number; base @f(y: 2, x: @g(x: 3, y: 4)) + @f(x: 5, y: 6); }}\n{work} w "Work" id "{ID(2)}" {{}}\ndiagram d "Diagram" id "{ID(5)}" {{ {layer} }}\n{extra}\n}}\n' files=[] for alias,name,n,op in [('f','F',10,'+'),('g','G',11,'-')]: files.append(f'calculation {alias} "{name}" id "{ID(n)}" {{\ninput x id "{ID(1)}" : Number;\ninput y id "{ID(12)}" : Number;\nresult Number; body $x {op} $y;\n}}\n'.encode()) return files+[main.encode()] G=lambda n:f'G{n}' P=lambda c,n:f'P{c}.{n}' rows=[] for file,c,alias in [(0,10,'f'),(1,11,'g')]: rows += [(file,12,13,G(c),alias),(file,68,69,P(c,1),'x'),(file,128,129,P(c,12),'y'),(file,203,204,P(c,1),'x'),(file,208,209,P(c,12),'y')] rows += [(2,a,a+1,t,s) for a,t,s in [(19,G(1),'p'),(122,G(4),'n'),(177,G(5),'d'),(189,G(3),'v'),(206,G(3),'v'),(269,G(2),'w'),(291,G(10),'f'),(293,P(10,12),'y'),(299,P(10,1),'x'),(303,G(11),'g'),(305,P(11,1),'x'),(311,P(11,12),'y'),(321,G(10),'f'),(323,P(10,1),'x'),(329,P(10,12),'y'),(350,G(2),'w'),(412,G(5),'d')]] changed={G(1):'w',G(2):'p',G(3):'n',G(4):'v',G(5):'z',G(10):'g',G(11):'f',P(10,1):'y',P(10,12):'x',P(11,1):'y',P(11,12):'x'} def check(files,edits,names): assert len(edits)==len({(f,a,b) for f,a,b,_,_ in edits}) assert set(t for _,_,_,t,_ in edits)==set(names) totals=[] for file,raw in enumerate(files): subset=sorted(x for x in edits if x[0]==file);last=0;removed=added=0 for _,a,b,target,spelling in subset: assert a>=last and raw[a:b]==spelling.encode();last=b;removed+=b-a;added+=len(names[target].encode()) totals.append((len(raw),removed,added,len(raw)-removed+added)) return totals for sa in (False,True): files=rich(sa);r=rows+([(2,490,491,G(6),'s')] if sa else []);names=changed|({G(6):'u'} if sa else {}) assert list(map(len,files))==[213,213,548 if sa else 474] transformed=[b'// '+bytes.fromhex('e99ba8')+b'\r\n'+raw.replace(b'\n',b'\r\n') for raw in files] tr=[(f,8+a+files[f][:a].count(b'\n'),8+b+files[f][:b].count(b'\n'),t,s) for f,a,b,t,s in r] print('RICH', 'SA' if sa else 'OA','R',len(names),'M',len(r),'E',15,'Q',len(names),'files',check(files,r,names),'CRLF',check(transformed,tr,names)) print('ORIGINAL',json.dumps(sorted(r)));print('TRANSFORMED',json.dumps(sorted(tr))) category=Path(__file__).resolve().parents[1]/'as3batch/crates/oa-core/src/language/analysis_source/mixed/project/ordinary_index/tests/fixtures/categories.arcadia' raw=category.read_bytes();assert len(raw)==2152 and hashlib.sha256(raw).hexdigest()=='3943579866157c7b5d95ce9edcb2d643058826b9af44257557e2864f130d15fc' old=['p','a','child','implicit','s','link','d','note','t','q','sub','use','left','right','context'] new=['a','p','implicit','child','link','s','note','d','q','t','use','sub','right','left','ctx'] positions=[(19,1),(168,2),(249,3),(344,2),(369,4),(487,5),(561,6),(625,3),(640,4),(664,7),(741,6),(789,6),(818,8),(885,6),(925,9),(992,3),(1003,5),(1328,10),(1391,12),(1397,14),(1422,11),(1487,13),(1514,12),(1577,10),(1617,11),(1648,13),(1712,11),(1741,3),(1789,14),(1855,10),(1882,4),(1935,15),(2004,10),(2029,12),(2047,13),(2092,14)] cr=[(0,a,a+len(old[n-1]),G(n),old[n-1]) for a,n in positions];cn={G(i+1):s for i,s in enumerate(new)} print('CATEGORY R15 M36 E0 Q15',check([raw],cr,cn));print('CATEGORY',json.dumps(cr)) files=rich();files[2]=files[2].replace(b'node n id',b'node '+b'n'*31+b' id') size_rows=[(0,12,13,G(10),'f'),(2,122,153,G(4),'n'*31),(2,321,322,G(10),'f'),(2,351,352,G(10),'f')] assert sum(map(len,files))==930 for alias,want in [('renamed_f',924),('renamed_func',933)]: totals=check(files,size_rows,{G(4):'n',G(10):alias}) assert sum(t[3] for t in totals)==want print('COMBINED SIZE',alias,totals,'total',want,'typed-only',930+3*(len(alias)-1)) print('PASS: authored raw token positions and separate removed/replacement lengths only; no application pipeline/output or semantic acceptance.')