summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/util/NameTransformer.scala
blob: 709bd00a840c3a8cbe970a75ad975dcb22f5938d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* NSC -- new scala compiler
 * Copyright 2005 LAMP/EPFL
 * @author  Martin Odersky
 */
// $Id$
package scala.tools.nsc.util;

object NameTransformer {
  private val nops = 128;
  private val ncodes = 26 * 26;

  private class OpCodes(val op: char, val code: String, val next: OpCodes);

  private val op2code = new Array[String](nops);
  private val code2op = new Array[OpCodes](ncodes);

  private def enterOp(op: char, code: String) = {
    op2code(op) = code;
    val c = (code.charAt(1) - 'a') * 26 + code.charAt(2) - 'a';
    code2op(c) = new OpCodes(op, code, code2op(c))
  }

  enterOp('~', "$tilde");
  enterOp('=', "$eq");
  enterOp('<', "$less");
  enterOp('>', "$greater");
  enterOp('!', "$bang");
  enterOp('#', "$hash");
  enterOp('%', "$percent");
  enterOp('^', "$up");
  enterOp('&', "$amp");
  enterOp('|', "$bar");
  enterOp('*', "$times");
  enterOp('/', "$div");
  enterOp('+', "$plus");
  enterOp('-', "$minus");
  enterOp(':', "$colon");
  enterOp('\\', "$bslash");

  /** Replace operator symbols by corresponding "$op_name" */
  def encode(name: String): String = {
    var buf: StringBuffer = null;
    val len = name.length();
    var i = 0;
    while (i < len) {
      val c = name charAt i;
      if (c < nops && op2code(c) != null) {
        if (buf == null) {
          buf = new StringBuffer();
          buf.append(name.substring(0, i));
        }
        buf.append(op2code(c));
      } else if (buf != null) {
        buf.append(c)
      }
      i = i + 1
    }
    if (buf == null) name else buf.toString()
  }

  /** Replace $op_name by corresponding operator symbol */
  def decode(name: String): String = {
    //System.out.println("decode: " + name);//DEBUG
    var buf: StringBuffer = null;
    val len = name.length();
    var i = 0;
    while (i < len) {
      var ops: OpCodes = null;
      val c = name charAt i;
      if (c == '$' && i + 2 < len) {
	val ch1 = name.charAt(i+1);
	if ('a' <= ch1 && ch1 <= 'z') {
	  val ch2 = name.charAt(i+2);
	  if ('a' <= ch2 && ch2 <= 'z') {
	    ops = code2op((ch1 - 'a') * 26 + ch2 - 'a');
	    while (ops != null && !name.startsWith(ops.code, i)) ops = ops.next;
	    if (ops != null) {
              if (buf == null) {
		buf = new StringBuffer();
		buf.append(name.substring(0, i));
              }
              buf.append(ops.op);
	      i = i + ops.code.length()
	    }
	  }
	}
      }
      if (ops == null) {
	if (buf != null) buf.append(c);
	i = i + 1
      }
    }
    //System.out.println("= " + (if (buf == null) name else buf.toString()));//DEBUG
    if (buf == null) name else buf.toString()
  }
}