1 package kawa.lang; 2 import gnu.lists.*; 3 import java.io.*; 4 import gnu.mapping.*; 5 import gnu.expr.*; 6 import java.util.*; 7 8 9 10 public class SyntaxTemplate implements Externalizable 11 { 12 21 String template_program; 22 23 24 static final int BUILD_MISC = 0; 25 26 27 static final int BUILD_LIST1 = (1<<3)+BUILD_MISC; 28 29 static final int BUILD_NIL = (2<<3)+BUILD_MISC; 30 31 32 static final int BUILD_SYNTAX = (3<<3)+BUILD_MISC; 33 34 36 static final int BUILD_VECTOR = (5<<3)+BUILD_MISC; 37 38 43 static final int BUILD_CONS = 1; 44 45 47 final static int BUILD_VAR = 2; 49 53 final static int BUILD_VAR_CAR = BUILD_VAR+1; 54 55 56 final static int BUILD_LITERAL = 4; 57 58 61 final static int BUILD_DOTS = 5; 62 63 64 final static int BUILD_WIDE = 7; 65 66 73 String patternNesting; 74 75 int max_nesting; 76 77 Object [] literal_values; 78 79 static final String dots3 = "..."; 80 81 147 148 149 protected SyntaxTemplate () 150 { 151 } 152 153 public SyntaxTemplate (String patternNesting, String template_program, 154 Object [] literal_values, int max_nesting) 155 { 156 this.patternNesting = patternNesting; 157 this.template_program = template_program; 158 this.literal_values = literal_values; 159 this.max_nesting = max_nesting; 160 } 161 162 public SyntaxTemplate (Object template, SyntaxForm syntax, Translator tr) 163 { 164 this.patternNesting = tr == null || tr.patternScope == null ? "" 165 : tr.patternScope.patternNesting.toString(); 166 StringBuffer program = new StringBuffer (); 167 java.util.Vector literals_vector = new java.util.Vector (); 168 169 IdentityHashMap seen = new IdentityHashMap(); 170 171 173 convert_template(template, syntax, 174 program, 0, literals_vector, seen, false, tr); 175 this.template_program = program.toString(); 176 this.literal_values = new Object [literals_vector.size ()]; 177 literals_vector.copyInto (this.literal_values); 178 179 195 } 196 197 209 public int convert_template (Object form, 210 SyntaxForm syntax, 211 StringBuffer template_program, 212 int nesting, 213 java.util.Vector literals_vector, 214 Object seen, 215 boolean isVector, 216 Translator tr) 217 { 218 while (form instanceof SyntaxForm) 219 { 220 syntax = (SyntaxForm) form; 221 form = syntax.form; 222 } 223 224 if (form instanceof Pair || form instanceof FVector) 225 { 226 IdentityHashMap seen_map = (IdentityHashMap) seen; 227 if (seen_map.containsKey(form)) 228 { 229 230 tr.syntaxError("self-referential (cyclic) syntax template"); 231 return -2; 232 } 233 seen_map.put(form, form); 234 } 235 236 237 check_form: 238 if (form instanceof Pair) 239 { 240 Pair pair = (Pair) form; 241 int ret_cdr = -2;; 242 int save_pc = template_program.length(); 243 Object car = pair.car; 244 245 if (tr.matches(car, dots3)) 247 { 248 Object cdr = Translator.stripSyntax(pair.cdr); 249 if (cdr instanceof Pair) 250 { 251 Pair cdr_pair = (Pair) cdr; 252 if (cdr_pair.car == dots3 && cdr_pair.cdr == LList.Empty) 253 { 254 form = dots3; 255 break check_form; 256 } 257 } 258 } 259 260 int save_literals = literals_vector.size(); 261 262 template_program.append((char) BUILD_LIST1); 264 265 int num_dots3 = 0; 266 Object rest = pair.cdr; 267 while (rest instanceof Pair) 268 { 269 Pair p = (Pair) rest; 270 if (! tr.matches(p.car, dots3)) 271 break; 272 num_dots3++; 273 rest = p.cdr; 274 template_program.append((char) BUILD_DOTS); } 276 int ret_car = convert_template(car, syntax, template_program, 277 nesting + num_dots3, 278 literals_vector, seen, false, tr); 279 280 if (rest != LList.Empty) 281 { 282 int delta = template_program.length() - save_pc - 1; 283 template_program.setCharAt(save_pc, 284 (char)((delta<<3)+BUILD_CONS)); 285 ret_cdr = convert_template (rest, syntax, 286 template_program, nesting, 287 literals_vector, seen, isVector, tr); 288 } 289 if (num_dots3 > 0) 290 { 291 if (ret_car < 0) 292 tr.syntaxError ("... follows template with no suitably-nested pattern variable"); 293 for (int i = num_dots3; --i >= 0; ) 294 { 295 char op = (char) ((ret_car << 3) + BUILD_DOTS); 296 template_program.setCharAt(save_pc+i + 1, op); 297 int n = nesting+num_dots3; 298 if (n >= max_nesting) 299 max_nesting = n; 300 } 301 } 302 if (ret_car >= 0) 303 return ret_car; 304 if (ret_cdr >= 0) 305 return ret_cdr; 306 if (ret_car == -1 || ret_cdr == -1) 307 return -1; 308 if (isVector) 309 return -2; 310 literals_vector.setSize(save_literals); 314 template_program.setLength(save_pc); 315 } 316 else if (form instanceof FVector) 317 { 318 template_program.append((char) BUILD_VECTOR); 319 return convert_template(LList.makeList((FVector) form), syntax, 320 template_program, nesting, 321 literals_vector, seen, true, tr); 322 } 323 else if (form == LList.Empty) 324 { 325 template_program.append((char) BUILD_NIL); 326 return -2; 327 } 328 else if (form instanceof String 329 && tr != null && tr.patternScope != null) 330 { 331 int pattern_var_num = indexOf(tr.patternScope.pattern_names, form); 332 if (pattern_var_num >= 0) 333 { 334 int var_nesting = patternNesting.charAt(pattern_var_num); 335 int op = (var_nesting & 1) != 0 ? BUILD_VAR_CAR : BUILD_VAR; 336 var_nesting >>= 1; 337 if (var_nesting > nesting) 341 tr.syntaxError ("inconsistent ... nesting of " + form); 342 template_program.append((char) (op + 8 * pattern_var_num)); 343 return var_nesting == nesting ? pattern_var_num : -1; 344 } 345 } 347 int literals_index = indexOf(literals_vector, form); 348 if (literals_index < 0) 349 { 350 literals_index = literals_vector.size (); 351 literals_vector.addElement(form); 352 } 353 if (form instanceof String || form instanceof Symbol) 354 tr.noteAccess(form, tr.currentScope()); 355 if (! (form instanceof SyntaxForm) && form != dots3) 356 template_program.append((char) (BUILD_SYNTAX)); 357 template_program.append((char) (BUILD_LITERAL + 8 * literals_index)); 358 return form == dots3 ? -1 : -2; 359 } 360 361 362 static int indexOf(java.util.Vector vec, Object elem) 363 { 364 int len = vec.size(); 365 for (int i = 0; i < len; i++) 366 { 367 if (vec.elementAt(i) == elem) 368 return i; 369 } 370 return -1; 371 } 372 373 374 private int get_count (Object var, int nesting, int[] indexes) 375 { 376 for (int level = 0; level < nesting; level++) 377 var = ((Object []) var) [indexes[level]]; 378 Object [] var_array = (Object []) var; 379 return var_array.length; 380 } 381 382 386 public Object execute (Object [] vars, TemplateScope templateScope) 387 { 388 if (false) { 390 OutPort err = OutPort.errDefault(); 391 err.print("{Expand template in "); 392 err.print(((Translator) Compilation.getCurrent()).getCurrentSyntax()); 393 err.print(" tscope: "); 394 err.print(templateScope); 395 if (false && vars != null) 396 { 397 err.print(" vars: "); 398 for (int i = 0; i < vars.length; i++) 399 { 400 err.println(); 401 err.print(" " + i +" : "); 402 kawa.standard.Scheme.writeFormat.writeObject(vars[i], err); 403 } 404 } 405 err.println('}'); 406 } 407 408 Object result = execute(0, vars, 0, new int[max_nesting], 409 (Translator) Compilation.getCurrent(), 410 templateScope); 411 412 if (false) { 414 OutPort err = OutPort.errDefault(); 415 err.startLogicalBlock("", false, "}"); 416 err.print("{Expansion of syntax template "); 417 err.print(((Translator) Compilation.getCurrent()).getCurrentSyntax()); 418 err.print(": "); 419 err.writeBreakLinear(); 420 kawa.standard.Scheme.writeFormat.writeObject(result, err); 421 err.endLogicalBlock("}"); 422 err.println(); 423 err.flush(); 424 } 425 return result; 426 } 427 428 public Object execute (Object [] vars, Translator tr, 429 TemplateScope templateScope) 430 { 431 return execute(0, vars, 0, new int[max_nesting], tr, templateScope); 432 } 433 434 Object get_var (int var_num, Object [] vars, int[] indexes) 435 { 436 Object var = vars [var_num]; 437 if (var_num < patternNesting.length()) 438 { 439 int var_nesting = (int) patternNesting.charAt(var_num) >> 1; 440 for (int level = 0; level < var_nesting; level++) 441 var = ((Object []) var) [indexes[level]]; 442 } 443 return var; 444 } 445 446 449 LList executeToList (int pc, Object [] vars, int nesting, int[] indexes, 450 Translator tr, TemplateScope templateScope) 451 { 452 int pc0 = pc; 453 int ch = template_program.charAt(pc); 454 while ((ch & 7) == BUILD_WIDE) 455 ch = ((ch - BUILD_WIDE) << 13) | template_program.charAt(++pc); 456 if ((ch & 7) == BUILD_VAR_CAR) 457 { 458 Pair p = (Pair) get_var(ch >> 3, vars, indexes); 459 return Translator.makePair(p, p.car, LList.Empty); 460 } 461 else if ((ch & 7) == BUILD_DOTS) 462 { 463 int var_num = (int) (ch >> 3); 464 Object var = vars[var_num]; 465 int count = get_count(var, nesting, indexes); 466 LList result = LList.Empty; 467 Pair last = null; pc++; 469 for (int j = 0; j < count; j++) 470 { 471 indexes[nesting] = j; 472 LList list 473 = executeToList(pc, vars, nesting + 1, indexes, tr, templateScope); 474 if (last == null) 475 result = list; 476 else 477 last.cdr = list; 478 while (list instanceof Pair) 481 { 482 last = (Pair) list; 483 list = (LList) last.cdr; 484 } 485 } 486 return result; 487 } 488 Object v = execute(pc0, vars, nesting, indexes, tr, templateScope); 489 return new Pair(v, LList.Empty); 490 } 491 492 497 Object execute (int pc, Object [] vars, int nesting, int[] indexes, 498 Translator tr, TemplateScope templateScope) 499 { 500 int ch = template_program.charAt(pc); 501 508 while ((ch & 7) == BUILD_WIDE) 509 ch = ((ch - BUILD_WIDE) << 13) | template_program.charAt(++pc); 510 if (ch == BUILD_LIST1) 511 { 512 return executeToList(pc+1, vars, nesting, indexes, tr, templateScope); 513 } 514 else if (ch == BUILD_NIL) 515 return LList.Empty; 516 else if (ch == BUILD_SYNTAX) 517 { 518 Object v = execute(pc+1, vars, nesting, indexes, tr, templateScope); 519 return v == LList.Empty ? v : SyntaxForm.make(v, templateScope); 520 } 521 else if ((ch & 7) == BUILD_CONS) 522 { 523 Pair p = null; 524 Object result = null; 525 for (;;) 526 { 527 pc++; 528 Object q 529 = executeToList(pc, vars, nesting, indexes, tr, templateScope); 530 if (p == null) 531 result = q; 532 else 533 p.cdr = q; 534 while (q instanceof Pair) 535 { 536 p = (Pair) q; 537 q = p.cdr; 538 } 539 pc += ch >> 3; 540 ch = template_program.charAt(pc); 541 if ((ch & 7) != BUILD_CONS) 542 break; 543 } 544 Object cdr = execute(pc, vars, nesting, indexes, tr, templateScope); 545 if (p == null) 546 result = cdr; 547 else 548 p.cdr = cdr; 549 return result; 550 } 551 else if (ch == BUILD_VECTOR) 552 { 553 Object el = execute(pc+1, vars, nesting, indexes, tr, templateScope); 554 return new FVector((LList) el); 555 } 556 else if ((ch & 7) == BUILD_LITERAL) 557 { 558 int lit_no = ch >> 3; 559 563 return literal_values[lit_no]; 564 } 565 else if ((ch & 6) == BUILD_VAR) { 567 Object var = get_var(ch >> 3, vars, indexes); 568 if ((ch & 7) == BUILD_VAR_CAR) 569 var = ((Pair) var).car; 570 return var; 571 } 572 else 573 throw new Error ("unknown template code: "+((int) ch)+" at "+pc); 574 } 575 576 579 public void writeExternal(ObjectOutput out) throws IOException 580 { 581 out.writeObject(patternNesting); 582 out.writeObject(template_program); 583 out.writeObject(literal_values); 584 out.writeInt(max_nesting); 585 } 586 587 public void readExternal(ObjectInput in) 588 throws IOException, ClassNotFoundException 589 { 590 patternNesting = (String ) in.readObject(); 591 template_program = (String ) in.readObject(); 592 literal_values = (Object []) in.readObject(); 593 max_nesting = in.readInt(); 594 } 595 } 596 | Popular Tags |