-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterp.hpp
More file actions
196 lines (169 loc) · 8.07 KB
/
Copy pathinterp.hpp
File metadata and controls
196 lines (169 loc) · 8.07 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// Ağaç yürüyen yorumlayıcı.
//
// Akış kontrolü (return/break/continue) ve RaidenScript istisnaları C++
// istisnalarıyla taşınıyor — tree-walk mimarisinde en temiz yol budur; her
// visit() metodunun bir "sinyal" döndürmesine gerek kalmıyor.
//
// Performans Faz 3'ün (bytecode VM) işi. Buradaki hedef DOĞRULUK.
#pragma once
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "ast.hpp"
#include "diag.hpp"
#include "lexer.hpp"
#include "parser.hpp"
#include "source.hpp"
#include "value.hpp"
namespace rs {
// --- akış sinyalleri ---
struct ReturnSignal { Value value; };
struct BreakSignal {};
struct ContinueSignal {};
// RaidenScript istisnası (throw ile fırlatılan veya çalışma zamanı hatası).
struct ScriptThrow {
Value value;
Span span;
};
class Interpreter final : public ExprVisitor, public StmtVisitor {
public:
Interpreter(const Source& src, Diagnostics& diag);
~Interpreter() override;
// Programı çalıştırır. Yakalanmamış istisna olursa false döner.
bool run(const Program& p);
// REPL için: tek bir deyimi çalıştırıp son ifade değerini döndürür.
[[nodiscard]] Value lastValue() const { return son_; }
// REPL her tur icin yeni bir Diagnostics kullaniyor.
void setDiagnostics(Diagnostics& d) { diag_ = &d; }
// --- gömme (Faz 4 / C API) ---
// Host'a giden çağrı. Betikteki 'game.spawnBullet(x, y)' buraya düşer.
//
// DİZE KANALI. Sınırın yalnızca sayı taşıması bilinçli bir karardı: sayı
// kopyalanır, sahiplik sorusu doğmaz. Ama metinsiz bir uygulama arayüzü
// yazılamıyor — IBAN, açıklama, hata mesajı hep dize. Çözüm dizeleri
// sayıya SIKIŞTIRMAK değil, argümanın yanında ayrı bir alanda taşımak:
// sayı yolu bir bayt değişmiyor, mevcut host'lar etkilenmiyor, ve
// "şu double aslında bir tutamak" gibi sessiz bir sözleşme doğmuyor.
struct HostArg {
double sayi = 0;
const std::string* dize = nullptr; // nullptr => argüman sayı
};
struct HostSonuc {
double sayi = 0;
bool dizeMi = false;
std::string dize;
// Host geri çağrısı istisnayla bitti. Köprü (capi.cpp) istisnayı DOĞDUĞU
// yerde yakalar ve buraya yazar; yorumlayıcı da bunu sıradan bir Error'a
// çevirir. İstisnanın yorumlayıcının karelerinden geçmesine izin vermek
// iki şeyi birden kırıyordu: 'extern "C"' sınırını aşmak tanımsız
// davranış, ve yıkıcıların çalışmadığı host'larda (wasm'da JS istisnası)
// derinlik_ geri alınmadan sızıyordu.
bool hataMi = false;
std::string hata;
};
using HostFn = std::function<HostSonuc(const std::string& modul, const std::string& fn,
const std::vector<HostArg>& args)>;
// Host'un sağladığı modül/fonksiyon çiftleri. 'include <modul>' görüldüğünde
// nil yerine bu tablodan bir harita bağlanır. eval'den ÖNCE kurulmalı.
void setHostBridge(std::vector<std::pair<std::string, std::string>> kayitli, HostFn cb);
// Global kapsamdaki bir fonksiyonu adıyla çağırır. Bulunamazsa ya da betik
// istisna fırlatırsa false döner; sebep diag_'a yazılır.
bool callGlobal(const std::string& ad, std::vector<Value>& args, Value& out);
// --- özyineleme koruması ---
//
// Ağaç yürüyen yorumlayıcıda bir betik karesi birkaç C++ karesi demek, ve
// taşma yakalanabilir bir hata DEĞİL: host sürecinin sessiz ölümü. Ölçüldü
// (faz5-web-tasarim.md H6): native 8 MB'ta ~1.000 kare, wasm 8 MB'ta ~1.000,
// JVM'in varsayılan 1 MB'ında ~500 — orada Java istisnası bile doğmuyor,
// Minecraft sunucusu tek satır iz bırakmadan kapanıyor.
//
// Varsayılan 800: native ve wasm'ın ölçülen sınırının altında. JVM gibi dar
// yığınlı host'lar setMaxDepth ile (C API: rs_set_max_depth) daha da indirir.
void setMaxDepth(int n) { maxDerinlik_ = n > 0 ? n : 1; }
[[nodiscard]] int maxDepth() const noexcept { return maxDerinlik_; }
private:
// 'include' için host haritası kurar; modül kayıtlı değilse nullopt.
std::optional<Value> hostModul(const std::string& modul);
// --- çekirdek ---
Value eval(const Expr* e);
void exec(const Stmt* s);
void execBlock(const std::vector<StmtPtr>& stmts, std::shared_ptr<Environment> env);
[[noreturn]] void hata(Span span, const std::string& mesaj, const std::string& ipucu = {});
[[nodiscard]] Value makeError(const std::string& mesaj);
// --- yardımcılar ---
Value cagir(const Value& callee, std::vector<Value>& args, Span span);
Value cagirFn(const std::shared_ptr<FnObj>& fn, std::vector<Value>& args, Span span,
const Value* self);
Value ikili(Tok op, const Value& a, const Value& b, Span span);
// Yerleşik metotların dize argümanı — tipi denetlenmeden okunursa çökme.
const std::string& dizeArg(std::vector<Value>& a, std::size_t i, const char* metot, Span span);
Value uyeOku(const Value& obj, const std::string& ad, Span span, bool guvenli);
Value indeksOku(const Value& obj, const Value& idx, Span span);
void indeksYaz(const Value& obj, const Value& idx, Value v, Span span);
Value yerlesikMetot(const Value& obj, const std::string& ad, Span span);
std::vector<Value> gezilebilir(const Value& v, Span span);
Value araligiAc(const RangeExpr& r, Span span);
void preludeKur();
void yerlesikSinifKur();
Value stdModul(const std::string& yol);
// --- ziyaretçi: ifadeler ---
void visit(const IntLit&) override;
void visit(const FloatLit&) override;
void visit(const StrLit&) override;
void visit(const FStrLit&) override;
void visit(const BoolLit&) override;
void visit(const NilLit&) override;
void visit(const Ident&) override;
void visit(const SelfExpr&) override;
void visit(const SuperExpr&) override;
void visit(const Unary&) override;
void visit(const Binary&) override;
void visit(const Logical&) override;
void visit(const Ternary&) override;
void visit(const RangeExpr&) override;
void visit(const Call&) override;
void visit(const IndexExpr&) override;
void visit(const Member&) override;
void visit(const Lambda&) override;
void visit(const ListLit&) override;
void visit(const MapLit&) override;
// --- ziyaretçi: deyimler ---
void visit(const ExprStmt&) override;
void visit(const AssignStmt&) override;
void visit(const Block&) override;
void visit(const IfStmt&) override;
void visit(const WhileStmt&) override;
void visit(const ForStmt&) override;
void visit(const BreakStmt&) override;
void visit(const ContinueStmt&) override;
void visit(const PassStmt&) override;
void visit(const ReturnStmt&) override;
void visit(const ThrowStmt&) override;
void visit(const TryStmt&) override;
void visit(const FnDecl&) override;
void visit(const ClassDecl&) override;
void visit(const TraitDecl&) override;
void visit(const ImportStmt&) override;
const Source* src_;
Diagnostics* diag_;
// --- gömme köprüsü ---
std::vector<std::pair<std::string, std::string>> hostKayit_; // (modül, fonksiyon)
HostFn hostFn_;
std::shared_ptr<Environment> globals_;
std::shared_ptr<Environment> env_;
Value son_; // en son değerlendirilen ifade
Value self_; // metot içindeyken geçerli örnek
std::shared_ptr<ClassObj> superOwner_; // 'super' çözümü için
std::shared_ptr<ClassObj> errorClass_;
int derinlik_ = 0; // o an açık olan betik çağrısı sayısı
int maxDerinlik_ = 800; // bkz. setMaxDepth
// Prelude, RaidenScript kaynağı olarak yazılıyor; AST'si programın ömrü
// boyunca yaşamalı, o yüzden burada tutuluyor.
std::unique_ptr<Source> preludeSrc_;
std::unique_ptr<Diagnostics> preludeDiag_;
std::unique_ptr<Program> preludeProg_;
};
} // namespace rs