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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
namespace Eva {
public interface Term : Object {
public abstract string to_string();
public bool equals(Term o) {
return (match(o) != null);
}
public Gee.Map<string, Term>? match(Term o) {
Gee.Map<string, Term> vars = new Gee.HashMap<string, Term>();
Gee.Map<string, string> aliases = new Gee.HashMap<string, string>();
if(!do_match(o, vars, aliases)) {
return null;
}
else {
foreach(string a in aliases.keys) {
string v = Var.alias(a, aliases);
if(v in vars)
vars[a] = vars[v];
}
return vars;
}
}
protected abstract bool do_match(Term o, Gee.Map<string, Term> vars, Gee.Map<string, string> aliases);
public abstract void encode(Erl.Buffer buffer);
public static Term decode(void *buffer) {
int index = 0;
int version;
Erl.decode_version(buffer, ref index, out version);
return do_decode(buffer, ref index);
}
private static Term do_decode(void *buffer, ref int index) {
int type, size;
assert(Erl.get_type(buffer, ref index, out type, out size) == 0);
switch(type) {
case Erl.TermType.SMALL_INTEGER:
char value;
assert(Erl.decode_char(buffer, ref index, out value) == 0);
return new Int((uchar)value);
case Erl.TermType.INTEGER:
long value;
assert(Erl.decode_long(buffer, ref index, out value) == 0);
return new Int(value);
case Erl.TermType.FLOAT:
double value;
assert(Erl.decode_double(buffer, ref index, out value) == 0);
return new Double(value);
case Erl.TermType.ATOM:
char[] value = new char[size+1];
assert(Erl.decode_atom(buffer, ref index, value) == 0);
return new Atom(array_to_string(value, size));
case Erl.TermType.SMALL_TUPLE:
case Erl.TermType.LARGE_TUPLE:
assert(Erl.decode_tuple_header(buffer, ref index, out size) == 0);
Term[] terms = new Term[size];
for(int i = 0; i < size; ++i) {
terms[i] = do_decode(buffer, ref index);
}
return new Tuple(terms);
case Erl.TermType.NIL:
case Erl.TermType.LIST:
List term = new List();
assert(Erl.decode_list_header(buffer, ref index, out size) == 0);
if(size != 0) {
for(int i = 0; i < size; ++i) {
term.list.add(do_decode(buffer, ref index));
}
term.tail = do_decode(buffer, ref index);
}
return term;
case Erl.TermType.STRING:
char[] value = new char[size+1];
assert(Erl.decode_string(buffer, ref index, value) == 0);
return new String(array_to_string(value, size));
case Erl.TermType.BINARY:
char[] value = new char[size];
long l;
assert(Erl.decode_binary(buffer, ref index, value, out l) == 0);
return new Binary(value);
case Erl.TermType.PID:
Erl.Pid value;
assert(Erl.decode_pid(buffer, ref index, out value) == 0);
return new Pid(value);
case Erl.TermType.PORT:
Erl.Port value;
assert(Erl.decode_port(buffer, ref index, out value) == 0);
return new Port(value);
case Erl.TermType.REFERENCE:
case Erl.TermType.NEW_REFERENCE:
Erl.Ref value;
assert(Erl.decode_ref(buffer, ref index, out value) == 0);
return new Ref(value);
default:
assert_not_reached();
}
}
}
}
|