@@ -50,7 +50,7 @@ long gk_alloc_budget=GK_ALLOC_BUDGET;
5050#endif
5151int opencode = 1 ;
5252char * pfile = "" ;
53- int gline ,glinei ,gline0 ,gline0i ,fileline ;
53+ int gline ,glinei ,gline0 ,gline0i ,fileline , filevirtual ;
5454
5555/* A projection of a LAMBDA is a noun, exactly like the lambda itself: a verb
5656 juxtaposed on its left applies (`,{x+y}[1]` enlists, as `,{x+y}` does), it
@@ -264,8 +264,15 @@ static void printerror(K v, K x0, int i) {
264264 char * ff0 = px (f0 );
265265 if (pline [i ]) { /* multiline lambda */
266266 if (strlen (pfile )) {
267- fprintf (stderr ,"%s ... + %d in %s:%d\n" ,ff0 ,pline [i ],pfile ,1 + pline [i ]+ ik (px0 [6 ]));
268- LOADLINE = 1 + pline [i ]+ ik (px0 [6 ]);
267+ i32 base = ik (px0 [6 ]);
268+ if (base < 0 ) {
269+ fprintf (stderr ,"%s ... + %d from %s:%d\n" ,ff0 ,pline [i ],pfile ,- base );
270+ LOADLINE = - base ;
271+ }
272+ else {
273+ fprintf (stderr ,"%s ... + %d in %s:%d\n" ,ff0 ,pline [i ],pfile ,1 + pline [i ]+ base );
274+ LOADLINE = 1 + pline [i ]+ base ;
275+ }
269276 }
270277 else fprintf (stderr ,"%s ... + %d\n" ,ff0 ,pline [i ]);
271278 kprint (v ,"" ,"\n" ,"" );
@@ -278,8 +285,9 @@ static void printerror(K v, K x0, int i) {
278285 }
279286 else { /* single line lambda */
280287 if (strlen (pfile )) {
281- fprintf (stderr ,"in %s:%d\n" ,pfile ,1 + ik (px0 [6 ]));
282- LOADLINE = 1 + ik (px0 [6 ]);
288+ i32 base = ik (px0 [6 ]);
289+ if (base < 0 ) { fprintf (stderr ,"from %s:%d\n" ,pfile ,- base ); LOADLINE = - base ; }
290+ else { fprintf (stderr ,"in %s:%d\n" ,pfile ,1 + base ); LOADLINE = 1 + base ; }
283291 }
284292 kprint (v ,"" ,"\n" ,"" );
285293 fprintf (stderr ,"%s\n" ,ff0 );
@@ -555,6 +563,9 @@ static K r44(K x) {
555563 return r ;
556564 }
557565
566+ /* The assign verbs ':' and '::' never take a bracket RHS */
567+ if (':' == f0 || 0x82 == s (f0 )) { _k (x ); return KERR_PARSE ; }
568+
558569 /* fast path: f[a;b;...] where f is a simple variable resolving to a
559570 0xc3 lambda, 0xd9 projection, or 0xda wrapper, and the param list
560571 is 0x41 or 0x81. Bypasses avb/strlen/strchr/snprintf and the
@@ -1277,7 +1288,9 @@ K pgreduce_(K x0, int *quiet) {
12771288 -- pA ;
12781289 b = * -- pA ;
12791290 a = * -- pA ;
1280- if (!a || !b ) { _k (a ); _k (b ); * pA ++ = KERR_TYPE ; break ; } /* backstop: never store/amend a NULL operand (mirrors the 0x81 guard above). Known producers are fixed at the push site, but the operand-stack-never-NULL invariant has several entry points. */
1291+ if (!a || !b ) { _k (a ); _k (b ); * pA ++ = KERR_TYPE ; break ; } /* backstop: never store/amend a NULL operand */
1292+ /* a bare bracket group is not a value */
1293+ if (0x41 == s (b )) { _k (a ); _k (b ); * pA ++ = KERR_PARSE ; break ; }
12811294 if (s (b )) { b = reduce (b ); if (E (b )|| EXIT ) { _k (a ); * pA ++ = b ; break ; } }
12821295 if (0x40 == s (a )) { /* a::1 */
12831296 if (!VST (b )) { _k (b ); * pA ++ = KERR_PARSE ; break ; }
@@ -1345,14 +1358,60 @@ K pgreduce_(K x0, int *quiet) {
13451358 if (pA <=A + 1 ) { k_ (v ); break ; }
13461359 -- pA ;
13471360 a = * -- pA ;
1348- if (0x40 != s (a )) { _k (a ); * pA ++ = KERR_VALUE ; break ; }
1349- if (KERR_VALUE == (a_ = vlookup (a ))) a_ = null ;
1350- if (E (a_ )) { * pA ++ = a_ ; break ; }
1351- t = k (strchr (P ,ik (v ))- P ,0 ,a_ );
1352- if (E (t )) { * pA ++ = t ; break ; };
1353- p = scope_set (cs ,a ,t );
1354- if (E (p )) { * pA ++ = p ; } /* t already freed by scope_set */
1355- else { * pA ++ = p ; * quiet = 1 ; }
1361+ if (0x40 == s (a )) {
1362+ K rs ; if (KERR_VALUE == (a_ = vlookuprs (a ,& rs ))) { a_ = null ; rs = scope_home (); }
1363+ if (E (a_ )) { * pA ++ = a_ ; break ; }
1364+ rs = asnrs (rs );
1365+ t = k (strchr (P ,ik (v ))- P ,0 ,a_ );
1366+ if (E (t )|| EXIT ) { * pA ++ = t ; break ; };
1367+ p = scope_set (rs ,a ,t );
1368+ if (E (p )) { * pA ++ = p ; } /* t already freed by scope_set */
1369+ else { * pA ++ = p ; * quiet = 1 ; }
1370+ }
1371+ else if (0x44 == s (a )) { /* a[0]-: - amend with the monad */
1372+ pa = px (a );
1373+ K target = pa [0 ]; K a_ = k_ (target ); K i_ = k_ (pa [1 ]); _k (a );
1374+ if (0x41 == s (i_ )) {
1375+ if (n (i_ )) {
1376+ i_ = r41 (i_ ); if (E (i_ )|| EXIT ) { _k (a_ ); * pA ++ = i_ ; break ; }
1377+ if (0x81 == s (i_ )) i_ = b (48 )& i_ ;
1378+ }
1379+ else { _k (i_ ); i_ = null ; }
1380+ }
1381+ else if (0x81 == s (i_ )) {
1382+ if (n (i_ )) i_ = b (48 )& i_ ;
1383+ else { _k (i_ ); i_ = null ; }
1384+ }
1385+ else { _k (a_ ); _k (i_ ); * pA ++ = KERR_TYPE ; break ; }
1386+ if (0x40 != s (a_ )) { _k (a_ ); _k (i_ ); * pA ++ = KERR_TYPE ; break ; }
1387+ // resolve, then apply closure check
1388+ K rs ; if (KERR_VALUE == (a_ = vlookuprs (a_ ,& rs ))) { a_ = null ; rs = scope_home (); }
1389+ if (E (a_ )) { _k (i_ ); * pA ++ = a_ ; break ; }
1390+ { K rsf = rs ; rs = asnrs (rsf );
1391+ /* redirected write (non-closure parent / namespace): the found
1392+ binding survives, so kamend3 must not amend it in place */
1393+ if (rs != rsf && a_ != null && (T (a_ )<=0 || T (a_ )== 2 ) && ((ko * )(b (48 )& a_ ))-> r ) {
1394+ K a2 = kcp (a_ ); _k (a_ ); a_ = a2 ;
1395+ if (E (a_ )) { _k (i_ ); * pA ++ = a_ ; break ; }
1396+ } }
1397+ K r = kamend3 (a_ ,k_ (i_ ),strchr (P ,ik (v ))- P );
1398+ if (E (r )) { _k (i_ ); * pA ++ = r ; }
1399+ else {
1400+ u64 zi = i + 1 ; while (zi < nx && 0x83 == s (px [zi ])) ++ zi ;
1401+ if (disc && zi >=nx ) { _k (i_ ); t = null ; } /* statement position: value freed unread */
1402+ else {
1403+ /* Compound assignment returns the selected values after the
1404+ complete amend (not the whole amended container). */
1405+ t = k (11 ,k_ (r ),i_ );
1406+ /* selection failure must not discard the completed write */
1407+ if (E (t )|| EXIT ) { if (t >=256 ) _k (t ); t = null ; }
1408+ }
1409+ p = scope_set (rs ,target ,r );
1410+ if (E (p )) { _k (t ); * pA ++ = p ; } /* r already freed by scope_set */
1411+ else { _k (p ); * pA ++ = t ; * quiet = 1 ; }
1412+ }
1413+ }
1414+ else { _k (a ); * pA ++ = KERR_VALUE ; break ; }
13561415 break ;
13571416 case 0xce : /* a+:1 */
13581417 if (pA <=A + 2 ) {
@@ -1932,7 +1991,8 @@ apply_n_fallback: {
19321991 }
19331992 break ;
19341993 case 2 : /* 64 64 66 ... */
1935- if (pA <=A + 1 ) { * pA ++ = KERR_VALENCE ; break ; }
1994+ /* an assign token with no target/value to consume is a malformed statement */
1995+ if (pA <=A + 1 ) { * pA ++ = KERR_PARSE ; break ; }
19361996 b = * -- pA ;
19371997 a = * -- pA ;
19381998
@@ -3710,7 +3770,7 @@ static K listbc(pgs *s, pn *a, int t) {
37103770 ((K * )px (pz [k ]))[3 ]= line ;
37113771 ((K * )px (pz [k ]))[4 ]= tnv (3 ,strlen (s -> file ),xmemdup (s -> file ,1 + strlen (s -> file )));
37123772 ((K * )px (pz [k ]))[5 ]= t (1 ,(u32 )a -> line ); // gline
3713- ((K * )px (pz [k ]))[6 ]= t (1 ,(u32 )fileline ); // ggline
3773+ ((K * )px (pz [k ]))[6 ]= t (1 ,(u32 )s -> fileline ); // ggline
37143774 bc (s ,a -> a [i ],values ,index ,line ,& vm );
37153775 if (n (values )== 1 ) {
37163776 pv = px (values );
@@ -4819,6 +4879,12 @@ K pgparse(char *q, int load, K locals) {
48194879 pz = px (z );
48204880 s -> p = q ;
48214881 s -> file = pfile ;
4882+ /* A negative frame base marks source reconstructed from a serialized
4883+ definition. Its relative lambda lines are real, but its file location is
4884+ only an anchor, so printerror prints "+N from FILE:LINE" without adding N
4885+ to the physical line. Keep the process-global fileline itself ordinary:
4886+ the lexer performs arithmetic on it while finding nested lambdas. */
4887+ s -> fileline = filevirtual ?~fileline :fileline ;
48224888 s -> valuesmax = 256 ;
48234889 s -> ti = 0 ;s -> tc = 0 ;s -> si = -1 ;s -> ri = -1 ;s -> vi = -1 ;
48244890 if (opencode ) stmt = ksplit (q ,"\r\n" );
@@ -4842,9 +4908,9 @@ K pgparse(char *q, int load, K locals) {
48424908 ((K * )px (pz [zn ]))[1 ]= index ;
48434909 ((K * )px (pz [zn ]))[2 ]= k_ (stmt );
48444910 ((K * )px (pz [zn ]))[3 ]= line ;
4845- ((K * )px (pz [zn ]))[4 ]= tnv (3 ,strlen (pfile ),xmemdup (pfile ,1 + strlen (pfile )));
4911+ ((K * )px (pz [zn ]))[4 ]= tnv (3 ,strlen (s -> file ),xmemdup (s -> file ,1 + strlen (s -> file )));
48464912 ((K * )px (pz [zn ]))[5 ]= t (1 ,(u32 )gline );
4847- ((K * )px (pz [zn ]))[6 ]= t (1 ,(u32 )fileline );
4913+ ((K * )px (pz [zn ]))[6 ]= t (1 ,(u32 )s -> fileline );
48484914 n (z )++ ;
48494915 s -> values = values ;
48504916 s -> index = index ;
0 commit comments