-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsidef_interpreter.sf
103 lines (86 loc) · 2.06 KB
/
sidef_interpreter.sf
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
#!/usr/bin/ruby
# A demo concept for a Sidef interpreter.
#
## Boolean type
#
class SBool(Bool val) {
}
#
## String type + methods
#
class SString(String val) {
method +(SString arg) {
SString(val + arg.val);
}
method say() {
self + SString("\n") -> print;
}
method print() {
SBool(Sys.print(val));
}
}
class Interpreter {
#
## Expression executor
#
method execute_expr(statement) {
statement.has_key(:self) || die "Invalid AST!";
var self_obj = statement{:self};
if (self_obj.is_a(Hash)) {
self_obj = self.execute(self_obj);
}
if (statement.has_key(:call)) {
statement{:call}.each { |call|
var meth = call{:method};
if (call.has_key(:arg)) {
var args = call{:arg}.map {|arg|
arg.is_a(Hash) ? self.execute_expr(arg) : arg
};
self_obj = self_obj.(meth)(args...);
}
else {
self_obj = self_obj.(meth);
}
}
};
return self_obj;
}
#
## Parse-tree executor
#
method execute(structure) {
var results = [];
structure.has_key(:main) || die "Invalid AST!";
structure{:main}.each { |statement|
results.append(self.execute_expr(statement));
};
results[-1];
}
}
#
## The AST
#
var ast = Hash.new(
:main => [
Hash.new(
:call => [Hash.new(:method => "print")],
:self => Hash.new(
:main => [
Hash.new(
:call => [Hash.new(:method => "+", :arg => [Hash.new(:self => SString("llo"))])],
:self => SString("he"),
)
],
)
),
Hash.new(
:call => [Hash.new(:method => "say")],
:self => SString(" world!");
),
]
);
#
## Begin execution
#
var intr = Interpreter();
intr.execute(ast);