i commited last idk when , so updates
This commit is contained in:
2967
csv/autos/cars.csv
Normal file
2967
csv/autos/cars.csv
Normal file
File diff suppressed because it is too large
Load Diff
35
csv/autos/main.py
Normal file
35
csv/autos/main.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: ansi -*-
|
||||||
|
import csv
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
def auswertung(csvf: str):
|
||||||
|
try:
|
||||||
|
with open(csvf, "r") as f:
|
||||||
|
reader = csv.reader(f, delimiter=";")
|
||||||
|
|
||||||
|
header = next(reader)
|
||||||
|
|
||||||
|
marken_count = defaultdict(int)
|
||||||
|
total_dataset = 0
|
||||||
|
|
||||||
|
for row in reader:
|
||||||
|
if len(row) < 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
total_dataset += 1
|
||||||
|
marke = row[1]
|
||||||
|
marken_count[marke] += 1
|
||||||
|
|
||||||
|
print(f"Insgesamt sind {total_dataset} Datens<6E>tze gespeichert!")
|
||||||
|
print(f"Insgesamt sind {len(marken_count)} verschiedene Automarken gespeichert!")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
for i, marke in enumerate(sorted(marken_count.keys()), start=1):
|
||||||
|
print(f"{i} : {marke} ist {marken_count[marke]} mal in der Liste gespeichert")
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auswertung("cars.csv")
|
||||||
2366
csv/gemeindenaut/gemeinden.csv
Normal file
2366
csv/gemeindenaut/gemeinden.csv
Normal file
File diff suppressed because it is too large
Load Diff
48
csv/gemeindenaut/main.py
Normal file
48
csv/gemeindenaut/main.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# -*- coding: ansi -*-
|
||||||
|
|
||||||
|
with open('gemeinden.csv', 'r') as file:
|
||||||
|
daten = file.readlines()
|
||||||
|
|
||||||
|
gemeinden_liste = []
|
||||||
|
for zeile in daten[1:]:
|
||||||
|
zeile = zeile.strip()
|
||||||
|
if zeile:
|
||||||
|
teile = zeile.split(';')
|
||||||
|
gemeinden_liste.append(teile)
|
||||||
|
|
||||||
|
for eintrag in gemeinden_liste:
|
||||||
|
eintrag[2] = int(eintrag[2])
|
||||||
|
|
||||||
|
bundeslaender = []
|
||||||
|
for eintrag in gemeinden_liste:
|
||||||
|
if eintrag[1] not in bundeslaender:
|
||||||
|
bundeslaender.append(eintrag[1])
|
||||||
|
|
||||||
|
einwohner_pro_bundesland = []
|
||||||
|
gemeinden_pro_bundesland = []
|
||||||
|
|
||||||
|
for i in range(len(bundeslaender)):
|
||||||
|
zwischensummen = []
|
||||||
|
for gemeinde, bundesland, einwohner in gemeinden_liste:
|
||||||
|
if bundeslaender[i] == bundesland:
|
||||||
|
zwischensummen.append(einwohner)
|
||||||
|
|
||||||
|
gesamt_einwohner = sum(zwischensummen)
|
||||||
|
anzahl_gemeinden = len(zwischensummen)
|
||||||
|
|
||||||
|
einwohner_pro_bundesland.append(gesamt_einwohner)
|
||||||
|
gemeinden_pro_bundesland.append(anzahl_gemeinden)
|
||||||
|
|
||||||
|
zwischensummen.clear()
|
||||||
|
|
||||||
|
print("Bundesl<EFBFBD>nder Statistik:")
|
||||||
|
for i in range(len(bundeslaender)):
|
||||||
|
print(f"{bundeslaender[i]}:")
|
||||||
|
print(f" Gemeinden: {gemeinden_pro_bundesland[i]}")
|
||||||
|
print(f" Einwohner: {einwohner_pro_bundesland[i]}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("\nZusammengefasste Statistik:")
|
||||||
|
print("Bundesland ; Gemeinden ; Einwohner")
|
||||||
|
for bundesland, gemeinden, einwohner in zip(bundeslaender, gemeinden_pro_bundesland, einwohner_pro_bundesland):
|
||||||
|
print(f"{bundesland:11} {gemeinden:8} {einwohner:9}")
|
||||||
36
csv/geschichtswiederholung/main.py
Normal file
36
csv/geschichtswiederholung/main.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: ansi -*-
|
||||||
|
# ^ geht ohne dem aus irgend einen grund nicht,
|
||||||
|
# wahrscheindlich wegen <20><><EFBFBD>
|
||||||
|
import csv
|
||||||
|
import random
|
||||||
|
|
||||||
|
def lade_schueler(dateiname):
|
||||||
|
schueler_verfuegbar = []
|
||||||
|
schueler_bereits_dran = []
|
||||||
|
|
||||||
|
with open(dateiname, newline='') as csvfile:
|
||||||
|
reader = csv.reader(csvfile, delimiter=';')
|
||||||
|
for row in reader:
|
||||||
|
name = f"{row[1]} {row[2]}"
|
||||||
|
if len(row) >= 4 and row[3].strip() == 'x':
|
||||||
|
schueler_bereits_dran.append(name)
|
||||||
|
else:
|
||||||
|
schueler_verfuegbar.append(name)
|
||||||
|
|
||||||
|
return schueler_verfuegbar, schueler_bereits_dran
|
||||||
|
|
||||||
|
def waehle_schueler(schueler_liste, anzahl=2):
|
||||||
|
return random.sample(schueler_liste, k=anzahl)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
datei = "schueler_6b_25.csv"
|
||||||
|
verfuegbare_schueler, bereits_dran = lade_schueler(datei)
|
||||||
|
|
||||||
|
print("Sch<EFBFBD>ler, die schon dran waren:")
|
||||||
|
for s in bereits_dran:
|
||||||
|
print(s)
|
||||||
|
|
||||||
|
gewaehlte_schueler = waehle_schueler(verfuegbare_schueler)
|
||||||
|
print("\nHeute dran sind:")
|
||||||
|
for s in gewaehlte_schueler:
|
||||||
|
print(s)
|
||||||
17
csv/geschichtswiederholung/schueler_6b_25.csv
Normal file
17
csv/geschichtswiederholung/schueler_6b_25.csv
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
1;Dhir;Vandita;x
|
||||||
|
2;Falk;Nico;
|
||||||
|
3;Geier;Sascha;
|
||||||
|
4;Hammer;Lena;
|
||||||
|
5;Hofstaetter;Elias;
|
||||||
|
6;Hohenscherer;Maximilian;
|
||||||
|
7;Moik;Niklas;
|
||||||
|
8;Okaemov;Ilia;
|
||||||
|
9;Ruiter;Celina;
|
||||||
|
10;Sam-Kandlhofer;Pia-Amelie;
|
||||||
|
11;Stecher;Mona;x
|
||||||
|
12;Strau<61>;Luzia;
|
||||||
|
13;Summerer;Anna;
|
||||||
|
14;Terler;Jeremias;
|
||||||
|
15;Trausmueller;Marie;
|
||||||
|
16;Zhang;Mark Lipeng;x
|
||||||
|
17;Zinkl;Sebastian;
|
||||||
|
BIN
csv/jahresbillanz/Jahresabrechnung.pdf
Normal file
BIN
csv/jahresbillanz/Jahresabrechnung.pdf
Normal file
Binary file not shown.
129
csv/jahresbillanz/Jahresabschluss.csv
Normal file
129
csv/jahresbillanz/Jahresabschluss.csv
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
1;7;Menz;14.10.2021;89343
|
||||||
|
2;7;Menz;18.07.2021;30386
|
||||||
|
3;12;Todt;15.12.2021;62144
|
||||||
|
4;7;Menz;29.11.2021;42775
|
||||||
|
5;6;Austin-Plass;18.08.2021;76751
|
||||||
|
6;12;Todt;12.08.2021;39197
|
||||||
|
7;5;Viessmann;13.09.2021;19197
|
||||||
|
8;4;Wengert;16.05.2021;28600
|
||||||
|
9;1;Meuter;17.11.2021;55596
|
||||||
|
10;11;Moldenhauer;26.11.2021;50758
|
||||||
|
11;5;Viessmann;27.07.2021;8689
|
||||||
|
12;1;Meuter;10.12.2021;37809
|
||||||
|
13;10;Rosin;26.06.2021;83176
|
||||||
|
14;4;Wengert;29.11.2021;88768
|
||||||
|
15;5;Viessmann;15.12.2021;8207
|
||||||
|
16;11;Moldenhauer;17.08.2021;31123
|
||||||
|
17;3;Denecke;26.11.2021;76931
|
||||||
|
18;9;Lohr;24.11.2021;48157
|
||||||
|
19;7;Menz;04.12.2021;13063
|
||||||
|
20;1;Meuter;23.11.2021;5316
|
||||||
|
21;8;Rabenstein-Niebel;19.10.2021;25511
|
||||||
|
22;4;Wengert;06.09.2021;22392
|
||||||
|
23;6;Austin-Plass;20.11.2021;73610
|
||||||
|
24;11;Moldenhauer;09.12.2021;47814
|
||||||
|
25;11;Moldenhauer;29.10.2021;79036
|
||||||
|
26;9;Lohr;17.09.2021;56846
|
||||||
|
27;8;Rabenstein-Niebel;17.11.2021;42504
|
||||||
|
28;12;Todt;18.10.2021;11364
|
||||||
|
29;10;Rosin;10.11.2021;86191
|
||||||
|
30;1;Meuter;28.09.2021;7825
|
||||||
|
31;2;Wassermann;20.11.2021;42028
|
||||||
|
32;6;Austin-Plass;12.12.2021;83780
|
||||||
|
33;9;Lohr;18.08.2021;16637
|
||||||
|
34;3;Denecke;11.08.2021;40530
|
||||||
|
35;2;Wassermann;21.10.2021;45040
|
||||||
|
36;12;Todt;03.12.2021;80563
|
||||||
|
37;8;Rabenstein-Niebel;23.11.2021;95791
|
||||||
|
38;3;Denecke;06.09.2021;46414
|
||||||
|
39;10;Rosin;14.10.2021;80264
|
||||||
|
40;2;Wassermann;04.06.2021;89811
|
||||||
|
41;4;Wengert;14.12.2021;64553
|
||||||
|
42;9;Lohr;14.08.2021;84744
|
||||||
|
43;5;Viessmann;19.06.2021;26610
|
||||||
|
44;1;Meuter;12.10.2021;76865
|
||||||
|
45;10;Rosin;23.08.2021;53399
|
||||||
|
46;9;Lohr;15.12.2021;51546
|
||||||
|
47;12;Todt;15.09.2021;56236
|
||||||
|
48;11;Moldenhauer;18.10.2021;97791
|
||||||
|
49;4;Wengert;05.11.2021;57798
|
||||||
|
50;11;Moldenhauer;14.07.2021;66082
|
||||||
|
51;1;Meuter;23.08.2021;92354
|
||||||
|
52;1;Meuter;02.11.2021;34725
|
||||||
|
53;6;Austin-Plass;10.09.2021;78096
|
||||||
|
54;2;Wassermann;18.11.2021;63008
|
||||||
|
55;5;Viessmann;07.12.2021;26777
|
||||||
|
56;7;Menz;11.10.2021;64434
|
||||||
|
57;5;Viessmann;01.12.2021;61780
|
||||||
|
58;8;Rabenstein-Niebel;25.11.2021;28412
|
||||||
|
59;5;Viessmann;11.12.2021;94470
|
||||||
|
60;5;Viessmann;16.11.2021;63232
|
||||||
|
61;1;Meuter;15.12.2021;52995
|
||||||
|
62;1;Meuter;26.07.2021;47502
|
||||||
|
63;6;Austin-Plass;16.11.2021;11970
|
||||||
|
64;7;Menz;27.08.2021;41099
|
||||||
|
65;8;Rabenstein-Niebel;23.09.2021;9731
|
||||||
|
66;4;Wengert;30.10.2021;40529
|
||||||
|
67;9;Lohr;13.11.2021;96884
|
||||||
|
68;7;Menz;16.11.2021;59037
|
||||||
|
69;12;Todt;01.12.2021;58291
|
||||||
|
70;6;Austin-Plass;06.12.2021;89049
|
||||||
|
71;1;Meuter;22.11.2021;45789
|
||||||
|
72;10;Rosin;12.12.2021;40103
|
||||||
|
73;6;Austin-Plass;08.12.2021;43460
|
||||||
|
74;9;Lohr;08.09.2021;67101
|
||||||
|
75;8;Rabenstein-Niebel;07.09.2021;58786
|
||||||
|
76;5;Viessmann;08.12.2021;15900
|
||||||
|
77;7;Menz;12.12.2021;21772
|
||||||
|
78;5;Viessmann;25.10.2021;93851
|
||||||
|
79;4;Wengert;04.11.2021;39161
|
||||||
|
80;6;Austin-Plass;25.08.2021;16163
|
||||||
|
81;5;Viessmann;12.12.2021;92294
|
||||||
|
82;4;Wengert;30.10.2021;58812
|
||||||
|
83;2;Wassermann;14.09.2021;32029
|
||||||
|
84;7;Menz;25.11.2021;43499
|
||||||
|
85;4;Wengert;09.10.2021;15812
|
||||||
|
86;7;Menz;19.10.2021;95050
|
||||||
|
87;8;Rabenstein-Niebel;19.11.2021;25591
|
||||||
|
88;11;Moldenhauer;31.08.2021;91529
|
||||||
|
89;2;Wassermann;12.12.2021;57046
|
||||||
|
90;6;Austin-Plass;21.10.2021;33695
|
||||||
|
91;1;Meuter;26.10.2021;86385
|
||||||
|
92;5;Viessmann;14.12.2021;66502
|
||||||
|
93;6;Austin-Plass;08.12.2021;59023
|
||||||
|
94;1;Meuter;15.08.2021;64730
|
||||||
|
95;5;Viessmann;25.11.2021;69062
|
||||||
|
96;7;Menz;01.10.2021;12994
|
||||||
|
97;2;Wassermann;29.10.2021;58183
|
||||||
|
98;4;Wengert;14.11.2021;9971
|
||||||
|
99;8;Rabenstein-Niebel;28.11.2021;40917
|
||||||
|
100;10;Rosin;06.11.2021;55297
|
||||||
|
101;10;Rosin;28.09.2021;67326
|
||||||
|
102;12;Todt;18.10.2021;96045
|
||||||
|
103;11;Moldenhauer;14.12.2021;91704
|
||||||
|
104;4;Wengert;15.12.2021;91638
|
||||||
|
105;2;Wassermann;16.11.2021;36078
|
||||||
|
106;4;Wengert;15.11.2021;13885
|
||||||
|
107;12;Todt;29.11.2021;21497
|
||||||
|
108;12;Todt;18.10.2021;67594
|
||||||
|
109;4;Wengert;12.10.2021;60347
|
||||||
|
110;6;Austin-Plass;13.12.2021;43526
|
||||||
|
111;8;Rabenstein-Niebel;30.07.2021;33822
|
||||||
|
112;11;Moldenhauer;08.12.2021;93547
|
||||||
|
113;9;Lohr;20.11.2021;48938
|
||||||
|
114;2;Wassermann;13.12.2021;49880
|
||||||
|
115;12;Todt;22.11.2021;57601
|
||||||
|
116;8;Rabenstein-Niebel;11.08.2021;24413
|
||||||
|
117;11;Moldenhauer;19.07.2021;79012
|
||||||
|
118;2;Wassermann;06.12.2021;89851
|
||||||
|
119;3;Denecke;11.10.2021;92338
|
||||||
|
120;6;Austin-Plass;24.10.2021;65368
|
||||||
|
121;6;Austin-Plass;05.12.2021;50949
|
||||||
|
122;10;Rosin;02.11.2021;9953
|
||||||
|
123;6;Austin-Plass;15.12.2021;59322
|
||||||
|
124;5;Viessmann;23.09.2021;90963
|
||||||
|
125;12;Todt;07.12.2021;17584
|
||||||
|
126;5;Viessmann;11.11.2021;7804
|
||||||
|
127;3;Denecke;19.11.2021;59752
|
||||||
|
128;3;Denecke;21.09.2021;30561
|
||||||
|
129;5;Viessmann;15.11.2021;5916
|
||||||
|
31
csv/jahresbillanz/main.py
Normal file
31
csv/jahresbillanz/main.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import csv
|
||||||
|
filename = "Jahresabschluss.csv"
|
||||||
|
|
||||||
|
firmen = []
|
||||||
|
rechnungssummen = []
|
||||||
|
|
||||||
|
with open(filename, newline='', encoding='utf-8') as csvfile:
|
||||||
|
reader = csv.reader(csvfile, delimiter=';')
|
||||||
|
next(reader)
|
||||||
|
for row in reader:
|
||||||
|
firmen.append(row[2])
|
||||||
|
rechnungssummen.append(float(row[4]))
|
||||||
|
|
||||||
|
einzigartige_firmen = []
|
||||||
|
for firma in firmen:
|
||||||
|
if firma not in einzigartige_firmen:
|
||||||
|
einzigartige_firmen.append(firma)
|
||||||
|
|
||||||
|
summen_pro_firma = []
|
||||||
|
|
||||||
|
for kunde in einzigartige_firmen:
|
||||||
|
gesamt = 0
|
||||||
|
for i in range(len(firmen)):
|
||||||
|
if firmen[i] == kunde:
|
||||||
|
gesamt += rechnungssummen[i]
|
||||||
|
summen_pro_firma.append(gesamt)
|
||||||
|
|
||||||
|
print("Jahresabschluss:")
|
||||||
|
for i in range(len(einzigartige_firmen)):
|
||||||
|
print(f"{einzigartige_firmen[i]}: {summen_pro_firma[i]:.2f} EUR")
|
||||||
22
csv/klassensprecherwahl/klassensprecher.csv
Normal file
22
csv/klassensprecherwahl/klassensprecher.csv
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Bernd
|
||||||
|
J<EFBFBD>rg
|
||||||
|
Alisa
|
||||||
|
Bernd
|
||||||
|
Alisa
|
||||||
|
Alisa
|
||||||
|
Alisa
|
||||||
|
Bernd
|
||||||
|
J<EFBFBD>rg
|
||||||
|
Julia
|
||||||
|
Bernd
|
||||||
|
Alisa
|
||||||
|
J<EFBFBD>rg
|
||||||
|
Julia
|
||||||
|
Alisa
|
||||||
|
Bernd
|
||||||
|
Julia
|
||||||
|
Julia
|
||||||
|
J<EFBFBD>rg
|
||||||
|
Bernd
|
||||||
|
Alisa
|
||||||
|
Alisa
|
||||||
|
38
csv/klassensprecherwahl/main.py
Normal file
38
csv/klassensprecherwahl/main.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
from collections import Counter
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
Sorry f<>r die sp<73>te Abgabe, war leider Krank.
|
||||||
|
Hab von Jeremias das beispiel angeschaut und versucht es zu verbessern.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def auswertung_datei(datei: str):
|
||||||
|
cwd = Path(os.getcwd())
|
||||||
|
pfad = cwd / datei
|
||||||
|
|
||||||
|
if not pfad.exists():
|
||||||
|
print(f"Datei '{datei}' nicht im aktuellen Ordner ({cwd}) gefunden.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with pfad.open("r", encoding="utf-8") as f:
|
||||||
|
namen = [zeile.strip() for zeile in f if zeile.strip()]
|
||||||
|
|
||||||
|
if not namen:
|
||||||
|
print("leer")
|
||||||
|
return
|
||||||
|
|
||||||
|
zaehler = Counter(namen)
|
||||||
|
|
||||||
|
print("Ergebnis der Klassensprecherwahl\n")
|
||||||
|
print(f"Es sind heuer {len(zaehler)} Kandidaten angetreten.\n")
|
||||||
|
|
||||||
|
for name, stimmen in zaehler.most_common():
|
||||||
|
print(f"{name}: {stimmen}")
|
||||||
|
|
||||||
|
sieger, stimmen = zaehler.most_common(1)[0]
|
||||||
|
print(f"\n{sieger} hat mit {stimmen} Stimmen gewonnen.")
|
||||||
|
|
||||||
|
auswertung_datei("klassensprecher.csv")
|
||||||
0
csv/vornamen/__init__.py
Normal file
0
csv/vornamen/__init__.py
Normal file
BIN
csv/vornamen/code.zip
Normal file
BIN
csv/vornamen/code.zip
Normal file
Binary file not shown.
60
csv/vornamen/main.py
Normal file
60
csv/vornamen/main.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# -*- coding: ansi -*-
|
||||||
|
from print_tables import tables
|
||||||
|
import csv
|
||||||
|
|
||||||
|
# Klassen-Daten einlesen
|
||||||
|
klassen = {
|
||||||
|
"s6a": [],
|
||||||
|
"s6b": [],
|
||||||
|
"s6c": [],
|
||||||
|
"s6ds": [],
|
||||||
|
"s6es": []
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open("vornamen_6kl_25.csv", "r", encoding="utf-8") as f:
|
||||||
|
reader = csv.reader(f, delimiter=";")
|
||||||
|
for row in reader:
|
||||||
|
for i, key in enumerate(klassen.keys()):
|
||||||
|
if i >= len(row):
|
||||||
|
continue
|
||||||
|
name = row[i].strip()
|
||||||
|
if name:
|
||||||
|
klassen[key].append(name)
|
||||||
|
except FileNotFoundError as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
# Alphabetisch sortieren und unique machen, aber Gesamtzahl vorher sichern
|
||||||
|
gesamtzahlen = {}
|
||||||
|
for key in klassen:
|
||||||
|
gesamtzahlen[key] = len(klassen[key]) # Anzahl aller Sch<63>ler inkl. Duplikate
|
||||||
|
klassen[key] = sorted(set(klassen[key])) # Unique + alphabetisch
|
||||||
|
|
||||||
|
# Originale Tabelle ausgeben
|
||||||
|
tables.print_table(klassen)
|
||||||
|
|
||||||
|
# Statistik vorbereiten
|
||||||
|
stats = {
|
||||||
|
"Klasse": [],
|
||||||
|
"Eigene Vornamen": [],
|
||||||
|
"Sch<EFBFBD>ler gesamt": []
|
||||||
|
}
|
||||||
|
|
||||||
|
gesamt_schueler = 0
|
||||||
|
for klasse, namen in klassen.items():
|
||||||
|
stats["Klasse"].append(klasse)
|
||||||
|
stats["Eigene Vornamen"].append(len(namen))
|
||||||
|
stats["Sch<EFBFBD>ler gesamt"].append(gesamtzahlen[klasse])
|
||||||
|
gesamt_schueler += gesamtzahlen[klasse]
|
||||||
|
|
||||||
|
# Statistik-Tabelle ausgeben
|
||||||
|
print("\nKlassenstatistik:")
|
||||||
|
tables.print_table(stats)
|
||||||
|
print(f"\nGesamtanzahl Sch<63>ler: {gesamt_schueler}")
|
||||||
|
|
||||||
|
# Alle unique Namen <20>ber alle Klassen
|
||||||
|
alle_namen = set()
|
||||||
|
for namen in klassen.values():
|
||||||
|
alle_namen.update(namen)
|
||||||
|
|
||||||
|
print(f"Gesamtzahl eigene Vornamen: {len(alle_namen)}")
|
||||||
38
csv/vornamen/print_tables.py
Normal file
38
csv/vornamen/print_tables.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
class tables:
|
||||||
|
@staticmethod
|
||||||
|
def print_table(data: dict, sum_row: dict = None):
|
||||||
|
"""
|
||||||
|
print a formatted table from a dict
|
||||||
|
:param data: dict with column names as keys and list of column values
|
||||||
|
:param sum_row: optional dict with the same keys for a sum/total row
|
||||||
|
"""
|
||||||
|
# Berechne die maximale Breite jeder Spalte (Header vs. Inhalte vs. Summe)
|
||||||
|
col_widths = {}
|
||||||
|
for k, v in data.items():
|
||||||
|
max_content_len = max((len(str(name)) for name in v), default=0)
|
||||||
|
header_len = len(k)
|
||||||
|
sum_len = len(str(sum_row[k])) if sum_row and k in sum_row else 0
|
||||||
|
col_widths[k] = max(max_content_len, header_len, sum_len)
|
||||||
|
|
||||||
|
# Header drucken
|
||||||
|
header = " | ".join(k.ljust(col_widths[k]) for k in data.keys())
|
||||||
|
separator = "-+-".join("-" * col_widths[k] for k in data.keys())
|
||||||
|
print(header)
|
||||||
|
print(separator)
|
||||||
|
|
||||||
|
# Zeilen drucken
|
||||||
|
max_len = max(len(v) for v in data.values())
|
||||||
|
for i in range(max_len):
|
||||||
|
row = []
|
||||||
|
for key in data.keys():
|
||||||
|
if i < len(data[key]):
|
||||||
|
row.append(str(data[key][i]).ljust(col_widths[key]))
|
||||||
|
else:
|
||||||
|
row.append(" " * col_widths[key])
|
||||||
|
print(" | ".join(row))
|
||||||
|
|
||||||
|
# Summe drucken, falls <20>bergeben
|
||||||
|
if sum_row:
|
||||||
|
print(separator)
|
||||||
|
sum_line = " | ".join(str(sum_row[k]).ljust(col_widths[k]) for k in data.keys())
|
||||||
|
print(sum_line)
|
||||||
28
csv/vornamen/vornamen_6kl_25.csv
Normal file
28
csv/vornamen/vornamen_6kl_25.csv
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Lilli Marie;Vandita;Adrian;Ho;Stella
|
||||||
|
Lena Maria;Nico;Emma;Kamilla;Benjamin
|
||||||
|
Miriam;Sascha;Ella;Nina;Linda
|
||||||
|
Valentina;Lena;Johanna;Matthias;Kevin
|
||||||
|
Emily;Elias;Jana;Nils;Luisa
|
||||||
|
Laura;Maximilian;Raphael;Jonathan;Anna
|
||||||
|
Eva;Niklas;Klara;Luka;Florian
|
||||||
|
Lara;Ilia;Sarah;Emilia;Elias
|
||||||
|
Mykyta;Celina;Frida;Emma;Hannah
|
||||||
|
Selina;Pia-Amelie;Anna;Matthias;Simon
|
||||||
|
Julia;Mona;Katrin;Tristan;Patrick
|
||||||
|
Anna-Lisa;Luzia;Maja;Jakab;Maximilian
|
||||||
|
David-Dimitrie;Anna;Sebastian;Paul;Timo
|
||||||
|
Sarah Marie;Jeremias;Sophia;Maximilian;Paul
|
||||||
|
Nicole;Marie;Sophie Luisa;Zoey;Paul
|
||||||
|
Pavlo;Mark Lipeng;Alice Isabell;Benedikt;Nico
|
||||||
|
Alexandra;Sebastian;Verena;Samuel;Anika
|
||||||
|
;;Valentina;Nina;Matteo
|
||||||
|
;;Anna;Moritz;Jakob
|
||||||
|
;;Illia;Patrick;
|
||||||
|
;;Larissa;Din;
|
||||||
|
;;Manuel;Dániel;
|
||||||
|
;;Anna;Theresa;
|
||||||
|
;;Michael;Michael;
|
||||||
|
;;Paula;Katharina;
|
||||||
|
;;Nina;;
|
||||||
|
;;Bianca;;
|
||||||
|
;;Felix;;
|
||||||
|
57
functions/klimahbfunc.py
Normal file
57
functions/klimahbfunc.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# -*- coding: ansi -*-
|
||||||
|
# Kopiert aus dem vorherigen Beispiel!
|
||||||
|
# Nur halt mit Funktionen
|
||||||
|
# Ich entschuldige mich für die verspätete abgabe!
|
||||||
|
temperaturen = [1.5, 3.2, 7.5, 12.3, 16.8, 20.1, 22.5, 21.9, 17.5, 12.0, 6.0, 2.5]
|
||||||
|
niederschlaege = [35, 42, 50, 60, 75, 90, 95, 80, 70, 65, 55, 40]
|
||||||
|
|
||||||
|
def durchschnitt(liste):
|
||||||
|
return sum(liste) / len(liste)
|
||||||
|
|
||||||
|
def durchschnitt_temperatur():
|
||||||
|
print(f"Durchschnittliche Jahrestemperatur: {durchschnitt(temperaturen):.2f} °C")
|
||||||
|
|
||||||
|
def durchschnitt_niederschlag():
|
||||||
|
print(f"Durchschnittlicher Jahresniederschlag: {durchschnitt(niederschlaege):.2f} mm")
|
||||||
|
|
||||||
|
def extrem_temperaturen():
|
||||||
|
print(f"Höchste Temperatur: {max(temperaturen)} °C")
|
||||||
|
print(f"Niedrigste Temperatur: {min(temperaturen)} °C")
|
||||||
|
|
||||||
|
def extrem_niederschlag():
|
||||||
|
print(f"Höchster Niederschlag: {max(niederschlaege)} mm")
|
||||||
|
print(f"Niedrigster Niederschlag: {min(niederschlaege)} mm")
|
||||||
|
|
||||||
|
def menue():
|
||||||
|
print("\n--- KLIMADATEN HARTBERG ---")
|
||||||
|
print("1: Durchschnittliche Jahrestemperatur")
|
||||||
|
print("2: Durchschnittlicher Jahresniederschlag")
|
||||||
|
print("3: Höchst- und Tiefsttemperatur")
|
||||||
|
print("4: Höchster und niedrigster Niederschlag")
|
||||||
|
print("5: Beenden")
|
||||||
|
|
||||||
|
def auswertung(wahl):
|
||||||
|
if wahl == "1":
|
||||||
|
durchschnitt_temperatur()
|
||||||
|
elif wahl == "2":
|
||||||
|
durchschnitt_niederschlag()
|
||||||
|
elif wahl == "3":
|
||||||
|
extrem_temperaturen()
|
||||||
|
elif wahl == "4":
|
||||||
|
extrem_niederschlag()
|
||||||
|
elif wahl == "5":
|
||||||
|
print("Programm beendet.")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("Ungültige Eingabe, bitte nochmals versuchen!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
laufend = True
|
||||||
|
while laufend:
|
||||||
|
menue()
|
||||||
|
wahl = input("Welche Auswertung möchten Sie? (1-5): ")
|
||||||
|
laufend = auswertung(wahl)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
25
jquery/ui/document.html
Normal file
25
jquery/ui/document.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="./progressbar.js"></script>
|
||||||
|
<script src="./easycard.js"></script>
|
||||||
|
|
||||||
|
<progress-bar id="progressbar-test" value="0"></progress-bar>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const bar = document.getElementById('progressbar-test');
|
||||||
|
for (let i = 0; i <= 100; i++) {
|
||||||
|
setTimeout(() => {
|
||||||
|
bar.value = i;
|
||||||
|
}, i * 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
74
jquery/ui/easycard.js
vendored
Normal file
74
jquery/ui/easycard.js
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* EasyCard Component
|
||||||
|
* <easy-card title="Card Title">
|
||||||
|
* <p>Put any content here: text, images, lists, etc.</p>
|
||||||
|
* </easy-card>
|
||||||
|
*/
|
||||||
|
|
||||||
|
class EasyCard extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const shadow = this.attachShadow({mode: 'open'});
|
||||||
|
|
||||||
|
// Create card container
|
||||||
|
this.card = document.createElement('div');
|
||||||
|
this.card.classList.add('easy-card');
|
||||||
|
|
||||||
|
// Create content container
|
||||||
|
this.content = document.createElement('div');
|
||||||
|
this.content.classList.add('easy-card-content');
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = `
|
||||||
|
.easy-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 8px 0;
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
.easy-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 18px rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
.easy-card-title {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.easy-card-content {
|
||||||
|
font-size: 1em;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
shadow.appendChild(style);
|
||||||
|
shadow.appendChild(this.card);
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
// Add title if provided
|
||||||
|
const titleText = this.getAttribute('title');
|
||||||
|
if (titleText) {
|
||||||
|
const title = document.createElement('h3');
|
||||||
|
title.classList.add('easy-card-title');
|
||||||
|
title.textContent = titleText;
|
||||||
|
this.card.appendChild(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move all light DOM content to the shadow DOM content container
|
||||||
|
const contentNodes = Array.from(this.childNodes);
|
||||||
|
contentNodes.forEach(node => {
|
||||||
|
this.content.appendChild(node.cloneNode(true));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.card.appendChild(this.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('easy-card', EasyCard);
|
||||||
84
jquery/ui/progressbar.js
vendored
Normal file
84
jquery/ui/progressbar.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* ProgressBar Component
|
||||||
|
* <progress-bar value="50"></progress-bar>
|
||||||
|
*
|
||||||
|
* This is a element with a Qt Styled Progressbar!
|
||||||
|
*
|
||||||
|
* utml 2025 - Utility Tag Markup Layer
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ProgressBar extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const shadow = this.attachShadow({mode: 'open'});
|
||||||
|
|
||||||
|
// Outer container
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.style.width = '300px';
|
||||||
|
container.style.height = '25px';
|
||||||
|
container.style.background = '#ddd';
|
||||||
|
container.style.borderRadius = '4px';
|
||||||
|
container.style.overflow = 'hidden';
|
||||||
|
container.style.position = 'relative';
|
||||||
|
|
||||||
|
// Inner value bar
|
||||||
|
const valueBar = document.createElement('div');
|
||||||
|
valueBar.style.width = '0%';
|
||||||
|
valueBar.style.height = '100%';
|
||||||
|
valueBar.style.backgroundColor = '#4a90e2';
|
||||||
|
valueBar.style.backgroundImage = `
|
||||||
|
linear-gradient(
|
||||||
|
45deg,
|
||||||
|
rgba(255,255,255,0.3) 25%,
|
||||||
|
rgba(255,255,255,0) 25%,
|
||||||
|
rgba(255,255,255,0) 50%,
|
||||||
|
rgba(255,255,255,0.3) 50%,
|
||||||
|
rgba(255,255,255,0.3) 75%,
|
||||||
|
rgba(255,255,255,0) 75%,
|
||||||
|
rgba(255,255,255,0) 100%
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
valueBar.style.backgroundSize = '40px 40px';
|
||||||
|
valueBar.style.animation = 'barberpole 1s linear infinite';
|
||||||
|
|
||||||
|
valueBar.style.transition = 'width 0.3s ease';
|
||||||
|
container.appendChild(valueBar);
|
||||||
|
|
||||||
|
// Add styles
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = `
|
||||||
|
@keyframes barberpole {
|
||||||
|
from { background-position: 0 0; }
|
||||||
|
to { background-position: 40px 0; } /* only horizontal movement */
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
shadow.appendChild(style);
|
||||||
|
shadow.appendChild(container);
|
||||||
|
|
||||||
|
this._valueBar = valueBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get observedAttributes() { return ['value']; }
|
||||||
|
|
||||||
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
|
if (name === 'value') {
|
||||||
|
const val = Math.min(100, Math.max(0, Number(newValue)));
|
||||||
|
this._valueBar.style.width = val + '%';
|
||||||
|
|
||||||
|
// Start/stop barber pole animation based on value
|
||||||
|
if (val < 100) {
|
||||||
|
this._valueBar.style.animation = 'barberpole 1s linear infinite';
|
||||||
|
} else {
|
||||||
|
this._valueBar.style.animation = 'none'; // stop animation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get value() { return Number(this.getAttribute('value')) || 0; }
|
||||||
|
set value(val) { this.setAttribute('value', val); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define custom element
|
||||||
|
customElements.define('progress-bar', ProgressBar);
|
||||||
@@ -12,8 +12,6 @@
|
|||||||
<Option name="RestoreCommandHistory">
|
<Option name="RestoreCommandHistory">
|
||||||
<Property name="History">
|
<Property name="History">
|
||||||
<Property value="gn" />
|
<Property value="gn" />
|
||||||
<Property value="g" />
|
|
||||||
<Property value="p" />
|
|
||||||
<Property value=".restart" />
|
<Property value=".restart" />
|
||||||
<Property value="uf mandelbrot!Render" />
|
<Property value="uf mandelbrot!Render" />
|
||||||
<Property value="x mandelbrot!Render" />
|
<Property value="x mandelbrot!Render" />
|
||||||
@@ -26,6 +24,10 @@
|
|||||||
<Property value="x mandelbrot!complex" />
|
<Property value="x mandelbrot!complex" />
|
||||||
<Property value="x mandelbrot!complex_scale" />
|
<Property value="x mandelbrot!complex_scale" />
|
||||||
<Property value="u 0x508360" />
|
<Property value="u 0x508360" />
|
||||||
|
<Property value="x mandelbrot!" />
|
||||||
|
<Property value="x mandelbrot!render" />
|
||||||
|
<Property value="p" />
|
||||||
|
<Property value="g" />
|
||||||
</Property>
|
</Property>
|
||||||
</Option>
|
</Option>
|
||||||
<Option name="RestoreBreakpoints">
|
<Option name="RestoreBreakpoints">
|
||||||
@@ -44,6 +46,20 @@
|
|||||||
<Property name="Line" value="47" />
|
<Property name="Line" value="47" />
|
||||||
<Property name="Type" value="Software" />
|
<Property name="Type" value="Software" />
|
||||||
</Property>
|
</Property>
|
||||||
|
<Property>
|
||||||
|
<Property name="Id" value="1" />
|
||||||
|
<Property name="IsEnabled" value="true" />
|
||||||
|
<Property name="OffsetExpression" value="" />
|
||||||
|
<Property name="Command" value="" />
|
||||||
|
<Property name="PassCount" value="1" />
|
||||||
|
<Property name="SymbolName" value="mandelbrot!Render" />
|
||||||
|
<Property name="Location" value="mandelbrot!Render" />
|
||||||
|
<Property name="Address" value="0" />
|
||||||
|
<Property name="Module" value="mandelbrot" />
|
||||||
|
<Property name="Filename" value="C:\Users\Sebastian\Desktop\INF6B\math\main.cpp" />
|
||||||
|
<Property name="Line" value="201" />
|
||||||
|
<Property name="Type" value="Software" />
|
||||||
|
</Property>
|
||||||
</Property>
|
</Property>
|
||||||
</Option>
|
</Option>
|
||||||
</TargetOptions>
|
</TargetOptions>
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
CC = gcc
|
|
||||||
CFLAGS = -Wall -Wextra -Werror -O2 -std=c99 -D_DEFAULT_SOURCE
|
|
||||||
CFLAGS += -fstack-protector-strong -D_FORTIFY_SOURCE=2
|
|
||||||
LDFLAGS = -z relro -z now
|
|
||||||
|
|
||||||
SOURCES = main.c vm_core.c
|
|
||||||
OBJECTS = $(SOURCES:.c=.o)
|
|
||||||
TARGET = popvm
|
|
||||||
|
|
||||||
all: $(TARGET)
|
|
||||||
|
|
||||||
$(TARGET): $(OBJECTS)
|
|
||||||
$(CC) $(LDFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJECTS) $(TARGET)
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#include "vm_types.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// Safe file reading
|
|
||||||
static uint8_t* read_file(const char* filename, size_t* size) {
|
|
||||||
FILE* file = fopen(filename, "rb");
|
|
||||||
if (!file) {
|
|
||||||
fprintf(stderr, "Cannot open file: %s\n", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
|
||||||
long file_size = ftell(file);
|
|
||||||
fseek(file, 0, SEEK_SET);
|
|
||||||
|
|
||||||
if (file_size <= 0 || file_size > 10 * 1024 * 1024) { // 10MB limit
|
|
||||||
fclose(file);
|
|
||||||
fprintf(stderr, "Invalid file size\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* buffer = malloc(file_size);
|
|
||||||
if (!buffer) {
|
|
||||||
fclose(file);
|
|
||||||
fprintf(stderr, "Memory allocation failed\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fread(buffer, 1, file_size, file) != (size_t)file_size) {
|
|
||||||
fclose(file);
|
|
||||||
free(buffer);
|
|
||||||
fprintf(stderr, "File read error\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
*size = file_size;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
if (argc != 2) {
|
|
||||||
printf("Usage: %s <file.popclass>\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t file_size;
|
|
||||||
uint8_t* bytecode = read_file(argv[1], &file_size);
|
|
||||||
if (!bytecode) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm_t* vm = vm_create(bytecode, file_size);
|
|
||||||
if (!vm) {
|
|
||||||
fprintf(stderr, "Failed to create VM\n");
|
|
||||||
free(bytecode);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vm_validate_bytecode(vm)) {
|
|
||||||
fprintf(stderr, "Invalid bytecode file\n");
|
|
||||||
vm_destroy(vm);
|
|
||||||
free(bytecode);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Executing program...\n");
|
|
||||||
vm_execute(vm);
|
|
||||||
printf("Program finished\n");
|
|
||||||
|
|
||||||
vm_destroy(vm);
|
|
||||||
free(bytecode);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Binary file not shown.
878
niacin/cpp/vm/vm.cpp
Normal file
878
niacin/cpp/vm/vm.cpp
Normal file
@@ -0,0 +1,878 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <variant>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <intrin.h>
|
||||||
|
#else
|
||||||
|
#include <x86intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// TYPE DEFINITIONS
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
enum class TypeCode : uint8_t {
|
||||||
|
I8 = 0x01, U8 = 0x02, I16 = 0x03, U16 = 0x04,
|
||||||
|
I32 = 0x05, U32 = 0x06, F32 = 0x07, BOOL = 0x08,
|
||||||
|
CHAR = 0x09, STR = 0x0A
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Opcode : uint8_t {
|
||||||
|
PUSH_CONST = 0x01, PUSH_INT = 0x02, PUSH_FLOAT = 0x03, PUSH_STR = 0x04,
|
||||||
|
LOAD_LOCAL = 0x10, STORE_LOCAL = 0x11,
|
||||||
|
ADD = 0x20, SUB = 0x21, MUL = 0x22, DIV = 0x23, MOD = 0x24,
|
||||||
|
NEG = 0x25, BIT_AND = 0x26, BIT_OR = 0x27, BIT_XOR = 0x28,
|
||||||
|
SHL = 0x29, SHR = 0x2A,
|
||||||
|
FADD = 0x30, FSUB = 0x31, FMUL = 0x32, FDIV = 0x33, FNEG = 0x34,
|
||||||
|
CMP_EQ = 0x40, CMP_NEQ = 0x41, CMP_LT = 0x42, CMP_GT = 0x43,
|
||||||
|
CMP_LE = 0x44, CMP_GE = 0x45,
|
||||||
|
JMP = 0x50, JMP_IF = 0x51, JMP_IF_NOT = 0x52,
|
||||||
|
CALL = 0x60, RET = 0x61,
|
||||||
|
CONST_CAST = 0x70, TRUNC = 0x71, TO_FLOAT = 0x72, TO_INT = 0x73,
|
||||||
|
DUP = 0x80, POP = 0x81,
|
||||||
|
PRINT = 0x90, HALT = 0xA0
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// VALUE REPRESENTATION WITH TYPE PUNNING FOR PERFORMANCE
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
union ValueData {
|
||||||
|
int32_t i32;
|
||||||
|
uint32_t u32;
|
||||||
|
float f32;
|
||||||
|
bool b;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
ValueData() : i32(0) {}
|
||||||
|
explicit ValueData(int32_t v) : i32(v) {}
|
||||||
|
explicit ValueData(uint32_t v) : u32(v) {}
|
||||||
|
explicit ValueData(float v) : f32(v) {}
|
||||||
|
explicit ValueData(bool v) : b(v) {}
|
||||||
|
explicit ValueData(char v) : c(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Value {
|
||||||
|
private:
|
||||||
|
TypeCode type_;
|
||||||
|
ValueData data_;
|
||||||
|
std::string str_data_; // Only for strings
|
||||||
|
|
||||||
|
public:
|
||||||
|
Value() : type_(TypeCode::I32), data_() {}
|
||||||
|
|
||||||
|
explicit Value(TypeCode type, int32_t value) : type_(type), data_(value) {}
|
||||||
|
explicit Value(TypeCode type, uint32_t value) : type_(type), data_(value) {}
|
||||||
|
explicit Value(TypeCode type, float value) : type_(type), data_(value) {}
|
||||||
|
explicit Value(TypeCode type, bool value) : type_(type), data_(value) {}
|
||||||
|
explicit Value(TypeCode type, char value) : type_(type), data_(value) {}
|
||||||
|
explicit Value(const std::string& value) : type_(TypeCode::STR), data_(), str_data_(value) {}
|
||||||
|
|
||||||
|
TypeCode type() const { return type_; }
|
||||||
|
|
||||||
|
int32_t as_i32() const {
|
||||||
|
switch (type_) {
|
||||||
|
case TypeCode::I8: case TypeCode::I16: case TypeCode::I32: return data_.i32;
|
||||||
|
case TypeCode::U8: case TypeCode::U16: case TypeCode::U32: return static_cast<int32_t>(data_.u32);
|
||||||
|
case TypeCode::F32: return static_cast<int32_t>(data_.f32);
|
||||||
|
case TypeCode::BOOL: return data_.b ? 1 : 0;
|
||||||
|
case TypeCode::CHAR: return static_cast<int32_t>(data_.c);
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t as_u32() const {
|
||||||
|
switch (type_) {
|
||||||
|
case TypeCode::I8: case TypeCode::I16: case TypeCode::I32: return static_cast<uint32_t>(data_.i32);
|
||||||
|
case TypeCode::U8: case TypeCode::U16: case TypeCode::U32: return data_.u32;
|
||||||
|
case TypeCode::F32: return static_cast<uint32_t>(data_.f32);
|
||||||
|
case TypeCode::BOOL: return data_.b ? 1 : 0;
|
||||||
|
case TypeCode::CHAR: return static_cast<uint32_t>(data_.c);
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float as_f32() const {
|
||||||
|
switch (type_) {
|
||||||
|
case TypeCode::I8: case TypeCode::I16: case TypeCode::I32: return static_cast<float>(data_.i32);
|
||||||
|
case TypeCode::U8: case TypeCode::U16: case TypeCode::U32: return static_cast<float>(data_.u32);
|
||||||
|
case TypeCode::F32: return data_.f32;
|
||||||
|
case TypeCode::BOOL: return data_.b ? 1.0f : 0.0f;
|
||||||
|
case TypeCode::CHAR: return static_cast<float>(data_.c);
|
||||||
|
default: return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool as_bool() const {
|
||||||
|
switch (type_) {
|
||||||
|
case TypeCode::BOOL: return data_.b;
|
||||||
|
case TypeCode::I8: case TypeCode::I16: case TypeCode::I32: return data_.i32 != 0;
|
||||||
|
case TypeCode::U8: case TypeCode::U16: case TypeCode::U32: return data_.u32 != 0;
|
||||||
|
case TypeCode::F32: return data_.f32 != 0.0f;
|
||||||
|
case TypeCode::CHAR: return data_.c != '\0';
|
||||||
|
case TypeCode::STR: return !str_data_.empty();
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& as_string() const { return str_data_; }
|
||||||
|
|
||||||
|
std::string to_string() const {
|
||||||
|
switch (type_) {
|
||||||
|
case TypeCode::I8: case TypeCode::I16: case TypeCode::I32: return std::to_string(data_.i32);
|
||||||
|
case TypeCode::U8: case TypeCode::U16: case TypeCode::U32: return std::to_string(data_.u32);
|
||||||
|
case TypeCode::F32: return std::to_string(data_.f32);
|
||||||
|
case TypeCode::BOOL: return data_.b ? "true" : "false";
|
||||||
|
case TypeCode::CHAR: return std::string(1, data_.c);
|
||||||
|
case TypeCode::STR: return str_data_;
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// JIT COMPILATION AND OPTIMIZATION
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
class JITCompiler {
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> native_code_;
|
||||||
|
size_t code_offset_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JITCompiler() : code_offset_(0) {}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
native_code_.clear();
|
||||||
|
code_offset_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void emit_bytes(const T* data, size_t size) {
|
||||||
|
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
|
||||||
|
native_code_.insert(native_code_.end(), bytes, bytes + size);
|
||||||
|
code_offset_ += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_byte(uint8_t b) {
|
||||||
|
native_code_.push_back(b);
|
||||||
|
code_offset_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_mov_rax_imm(int32_t value) {
|
||||||
|
emit_byte(0x48); // REX.W
|
||||||
|
emit_byte(0xB8); // MOV RAX, imm64
|
||||||
|
emit_bytes(&value, sizeof(value));
|
||||||
|
// Pad to 8 bytes
|
||||||
|
int32_t zero = 0;
|
||||||
|
emit_bytes(&zero, sizeof(zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_mov_rbx_imm(int32_t value) {
|
||||||
|
emit_byte(0x48); // REX.W
|
||||||
|
emit_byte(0xBB); // MOV RBX, imm64
|
||||||
|
emit_bytes(&value, sizeof(value));
|
||||||
|
int32_t zero = 0;
|
||||||
|
emit_bytes(&zero, sizeof(zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_add_rax_rbx() {
|
||||||
|
emit_byte(0x48); // REX.W
|
||||||
|
emit_byte(0x01); // ADD
|
||||||
|
emit_byte(0xD8); // RAX, RBX
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_ret() {
|
||||||
|
emit_byte(0xC3); // RET
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t>& get_code() const { return native_code_; }
|
||||||
|
|
||||||
|
// Execute generated native code
|
||||||
|
int32_t execute() {
|
||||||
|
if (native_code_.empty()) return 0;
|
||||||
|
|
||||||
|
// In a real implementation, we'd use mmap with PROT_EXEC
|
||||||
|
// For safety, we'll simulate execution
|
||||||
|
std::cout << "[JIT] Executing optimized native code ("
|
||||||
|
<< native_code_.size() << " bytes)" << std::endl;
|
||||||
|
return 42; // Simulated result
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// HOT CODE DETECTOR AND OPTIMIZER
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
class HotCodeDetector {
|
||||||
|
private:
|
||||||
|
struct BlockInfo {
|
||||||
|
size_t execution_count;
|
||||||
|
size_t start_ip;
|
||||||
|
size_t end_ip;
|
||||||
|
std::vector<uint8_t> bytecode;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<size_t, BlockInfo> hot_blocks_;
|
||||||
|
size_t threshold_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
HotCodeDetector(size_t threshold = 1000) : threshold_(threshold) {}
|
||||||
|
|
||||||
|
void record_execution(size_t ip, const std::vector<uint8_t>& bytecode, size_t block_size) {
|
||||||
|
auto it = hot_blocks_.find(ip);
|
||||||
|
if (it == hot_blocks_.end()) {
|
||||||
|
BlockInfo info;
|
||||||
|
info.execution_count = 1;
|
||||||
|
info.start_ip = ip;
|
||||||
|
info.end_ip = ip + block_size;
|
||||||
|
info.bytecode.assign(bytecode.begin() + ip, bytecode.begin() + ip + block_size);
|
||||||
|
hot_blocks_[ip] = info;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it->second.execution_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_hot(size_t ip) const {
|
||||||
|
auto it = hot_blocks_.find(ip);
|
||||||
|
return it != hot_blocks_.end() && it->second.execution_count >= threshold_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BlockInfo* get_hot_block(size_t ip) const {
|
||||||
|
auto it = hot_blocks_.find(ip);
|
||||||
|
return (it != hot_blocks_.end() && it->second.execution_count >= threshold_) ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void optimize_block(const BlockInfo& block, JITCompiler& jit) {
|
||||||
|
// Simple JIT: convert basic arithmetic operations to native code
|
||||||
|
size_t ip = 0;
|
||||||
|
const auto& code = block.bytecode;
|
||||||
|
|
||||||
|
while (ip < code.size()) {
|
||||||
|
Opcode op = static_cast<Opcode>(code[ip++]);
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case Opcode::PUSH_INT: {
|
||||||
|
// Skip width and value
|
||||||
|
ip += 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Opcode::ADD: {
|
||||||
|
jit.emit_add_rax_rbx();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Opcode::PUSH_CONST: {
|
||||||
|
// Would need constant processing
|
||||||
|
ip += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// Can't optimize this opcode in simple JIT
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jit.emit_ret();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// HIGH-PERFORMANCE VM WITH JIT
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
class OptimizedVM {
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> bytecode_;
|
||||||
|
std::vector<Value> constants_;
|
||||||
|
std::vector<std::vector<Value>> functions_;
|
||||||
|
|
||||||
|
// Execution state
|
||||||
|
size_t ip_;
|
||||||
|
std::vector<Value> stack_;
|
||||||
|
std::vector<std::vector<Value>> call_stack_;
|
||||||
|
std::vector<Value> locals_;
|
||||||
|
bool halted_;
|
||||||
|
|
||||||
|
// Optimization components
|
||||||
|
HotCodeDetector hot_detector_;
|
||||||
|
JITCompiler jit_compiler_;
|
||||||
|
std::unordered_map<size_t, std::function<Value()>> jit_cache_;
|
||||||
|
|
||||||
|
// Inline cache for method calls
|
||||||
|
struct InlineCacheEntry {
|
||||||
|
size_t target_func;
|
||||||
|
size_t call_count;
|
||||||
|
};
|
||||||
|
std::unordered_map<size_t, InlineCacheEntry> inline_cache_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OptimizedVM() : ip_(0), halted_(false), hot_detector_(100) {}
|
||||||
|
|
||||||
|
bool load_bytecode(const std::vector<uint8_t>& bytecode) {
|
||||||
|
bytecode_ = bytecode;
|
||||||
|
return parse_bytecode();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_bytecode_from_file(const std::string& filename) {
|
||||||
|
std::ifstream file(filename, std::ios::binary);
|
||||||
|
if (!file) return false;
|
||||||
|
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
size_t size = file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
bytecode_.resize(size);
|
||||||
|
file.read(reinterpret_cast<char*>(bytecode_.data()), size);
|
||||||
|
|
||||||
|
return parse_bytecode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool parse_bytecode() {
|
||||||
|
// Simplified parser - real implementation would parse .popclass format
|
||||||
|
if (bytecode_.size() < 4 || std::string(bytecode_.begin(), bytecode_.begin() + 4) != "POPC") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ip_ = 8; // Skip header
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t fetch_byte() {
|
||||||
|
return bytecode_[ip_++];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t fetch_u16() {
|
||||||
|
uint16_t value;
|
||||||
|
std::memcpy(&value, &bytecode_[ip_], sizeof(value));
|
||||||
|
ip_ += sizeof(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t fetch_u32() {
|
||||||
|
uint32_t value;
|
||||||
|
std::memcpy(&value, &bytecode_[ip_], sizeof(value));
|
||||||
|
ip_ += sizeof(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t fetch_i32() {
|
||||||
|
int32_t value;
|
||||||
|
std::memcpy(&value, &bytecode_[ip_], sizeof(value));
|
||||||
|
ip_ += sizeof(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float fetch_f32() {
|
||||||
|
float value;
|
||||||
|
std::memcpy(&value, &bytecode_[ip_], sizeof(value));
|
||||||
|
ip_ += sizeof(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(const Value& value) {
|
||||||
|
stack_.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value pop() {
|
||||||
|
if (stack_.empty()) throw std::runtime_error("Stack underflow");
|
||||||
|
Value value = stack_.back();
|
||||||
|
stack_.pop_back();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value& peek(size_t offset = 0) {
|
||||||
|
if (offset >= stack_.size()) throw std::runtime_error("Stack peek out of bounds");
|
||||||
|
return stack_[stack_.size() - 1 - offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void run(bool enable_jit = true) {
|
||||||
|
ip_ = 0;
|
||||||
|
halted_ = false;
|
||||||
|
stack_.clear();
|
||||||
|
call_stack_.clear();
|
||||||
|
locals_.clear();
|
||||||
|
|
||||||
|
// Main execution loop with performance counters
|
||||||
|
size_t instructions_executed = 0;
|
||||||
|
auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
while (!halted_ && ip_ < bytecode_.size()) {
|
||||||
|
// Check for JIT-optimized block
|
||||||
|
if (enable_jit) {
|
||||||
|
auto jit_it = jit_cache_.find(ip_);
|
||||||
|
if (jit_it != jit_cache_.end()) {
|
||||||
|
Value result = jit_it->second();
|
||||||
|
push(result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for hot code blocks
|
||||||
|
if (hot_detector_.is_hot(ip_)) {
|
||||||
|
const auto* hot_block = hot_detector_.get_hot_block(ip_);
|
||||||
|
if (hot_block) {
|
||||||
|
std::cout << "[JIT] Compiling hot block at 0x"
|
||||||
|
<< std::hex << ip_ << std::dec << std::endl;
|
||||||
|
jit_compiler_.reset();
|
||||||
|
hot_detector_.optimize_block(*hot_block, jit_compiler_);
|
||||||
|
|
||||||
|
// Cache the JIT function
|
||||||
|
auto jit_func = [this]() -> Value {
|
||||||
|
return Value(TypeCode::I32, jit_compiler_.execute());
|
||||||
|
};
|
||||||
|
jit_cache_[ip_] = jit_func;
|
||||||
|
|
||||||
|
// Execute JIT version
|
||||||
|
Value result = jit_func();
|
||||||
|
push(result);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record execution for hot code detection
|
||||||
|
hot_detector_.record_execution(ip_, bytecode_, 16); // Monitor 16-byte blocks
|
||||||
|
|
||||||
|
execute_instruction();
|
||||||
|
instructions_executed++;
|
||||||
|
|
||||||
|
// Basic bounds checking
|
||||||
|
if (stack_.size() > 1000000) {
|
||||||
|
throw std::runtime_error("Stack overflow protection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end_time = std::chrono::high_resolution_clock::now();
|
||||||
|
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
|
||||||
|
|
||||||
|
std::cout << "Execution completed: " << instructions_executed
|
||||||
|
<< " instructions in " << duration.count() << " μs ("
|
||||||
|
<< (instructions_executed * 1000000.0 / duration.count())
|
||||||
|
<< " instructions/sec)" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void execute_instruction() {
|
||||||
|
Opcode opcode = static_cast<Opcode>(fetch_byte());
|
||||||
|
|
||||||
|
switch (opcode) {
|
||||||
|
case Opcode::PUSH_INT: {
|
||||||
|
uint8_t width = fetch_byte();
|
||||||
|
int32_t value = fetch_i32();
|
||||||
|
push(Value(TypeCode::I32, value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::PUSH_FLOAT: {
|
||||||
|
float value = fetch_f32();
|
||||||
|
push(Value(TypeCode::F32, value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::PUSH_CONST: {
|
||||||
|
uint32_t const_idx = fetch_u32();
|
||||||
|
if (const_idx < constants_.size()) {
|
||||||
|
push(constants_[const_idx]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::LOAD_LOCAL: {
|
||||||
|
uint16_t local_idx = fetch_u16();
|
||||||
|
if (local_idx < locals_.size()) {
|
||||||
|
push(locals_[local_idx]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::STORE_LOCAL: {
|
||||||
|
uint16_t local_idx = fetch_u16();
|
||||||
|
Value value = pop();
|
||||||
|
if (local_idx >= locals_.size()) {
|
||||||
|
locals_.resize(local_idx + 1);
|
||||||
|
}
|
||||||
|
locals_[local_idx] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::ADD: {
|
||||||
|
Value b = pop();
|
||||||
|
Value a = pop();
|
||||||
|
|
||||||
|
// Type-based dispatch for performance
|
||||||
|
if (a.type() == TypeCode::F32 || b.type() == TypeCode::F32) {
|
||||||
|
float result = a.as_f32() + b.as_f32();
|
||||||
|
push(Value(TypeCode::F32, result));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int32_t result = a.as_i32() + b.as_i32();
|
||||||
|
push(Value(TypeCode::I32, result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::SUB: {
|
||||||
|
Value b = pop();
|
||||||
|
Value a = pop();
|
||||||
|
|
||||||
|
if (a.type() == TypeCode::F32 || b.type() == TypeCode::F32) {
|
||||||
|
float result = a.as_f32() - b.as_f32();
|
||||||
|
push(Value(TypeCode::F32, result));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int32_t result = a.as_i32() - b.as_i32();
|
||||||
|
push(Value(TypeCode::I32, result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::MUL: {
|
||||||
|
Value b = pop();
|
||||||
|
Value a = pop();
|
||||||
|
|
||||||
|
if (a.type() == TypeCode::F32 || b.type() == TypeCode::F32) {
|
||||||
|
float result = a.as_f32() * b.as_f32();
|
||||||
|
push(Value(TypeCode::F32, result));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int32_t result = a.as_i32() * b.as_i32();
|
||||||
|
push(Value(TypeCode::I32, result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::DIV: {
|
||||||
|
Value b = pop();
|
||||||
|
Value a = pop();
|
||||||
|
|
||||||
|
if (b.as_f32() == 0.0f) {
|
||||||
|
throw std::runtime_error("Division by zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.type() == TypeCode::F32 || b.type() == TypeCode::F32) {
|
||||||
|
float result = a.as_f32() / b.as_f32();
|
||||||
|
push(Value(TypeCode::F32, result));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int32_t result = a.as_i32() / b.as_i32();
|
||||||
|
push(Value(TypeCode::I32, result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::CMP_EQ: {
|
||||||
|
Value b = pop();
|
||||||
|
Value a = pop();
|
||||||
|
bool result = (a.as_i32() == b.as_i32());
|
||||||
|
push(Value(TypeCode::BOOL, result));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::CMP_LT: {
|
||||||
|
Value b = pop();
|
||||||
|
Value a = pop();
|
||||||
|
|
||||||
|
if (a.type() == TypeCode::F32 || b.type() == TypeCode::F32) {
|
||||||
|
bool result = a.as_f32() < b.as_f32();
|
||||||
|
push(Value(TypeCode::BOOL, result));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bool result = a.as_i32() < b.as_i32();
|
||||||
|
push(Value(TypeCode::BOOL, result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::JMP: {
|
||||||
|
int32_t offset = fetch_i32();
|
||||||
|
ip_ += offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::JMP_IF: {
|
||||||
|
int32_t offset = fetch_i32();
|
||||||
|
Value cond = pop();
|
||||||
|
if (cond.as_bool()) {
|
||||||
|
ip_ += offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::JMP_IF_NOT: {
|
||||||
|
int32_t offset = fetch_i32();
|
||||||
|
Value cond = pop();
|
||||||
|
if (!cond.as_bool()) {
|
||||||
|
ip_ += offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::CALL: {
|
||||||
|
uint16_t func_idx = fetch_u16();
|
||||||
|
uint8_t arg_count = fetch_byte();
|
||||||
|
|
||||||
|
// Prepare arguments
|
||||||
|
std::vector<Value> args;
|
||||||
|
for (int i = 0; i < arg_count; ++i) {
|
||||||
|
args.push_back(pop());
|
||||||
|
}
|
||||||
|
std::reverse(args.begin(), args.end());
|
||||||
|
|
||||||
|
// Save execution state
|
||||||
|
call_stack_.push_back(locals_);
|
||||||
|
call_stack_.push_back(std::vector<Value>{Value(TypeCode::I32, static_cast<int32_t>(ip_))});
|
||||||
|
|
||||||
|
// Set up new frame
|
||||||
|
locals_ = args;
|
||||||
|
ip_ = 0; // Simplified - real implementation would use function table
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::RET: {
|
||||||
|
uint8_t has_value = fetch_byte();
|
||||||
|
Value return_value;
|
||||||
|
if (has_value) {
|
||||||
|
return_value = pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (call_stack_.size() < 2) {
|
||||||
|
halted_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore execution state
|
||||||
|
std::vector<Value> return_ip_vec = call_stack_.back();
|
||||||
|
call_stack_.pop_back();
|
||||||
|
locals_ = call_stack_.back();
|
||||||
|
call_stack_.pop_back();
|
||||||
|
|
||||||
|
if (!return_ip_vec.empty()) {
|
||||||
|
ip_ = return_ip_vec[0].as_i32();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_value) {
|
||||||
|
push(return_value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::DUP: {
|
||||||
|
if (!stack_.empty()) {
|
||||||
|
push(stack_.back());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::POP: {
|
||||||
|
if (!stack_.empty()) {
|
||||||
|
stack_.pop_back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::PRINT: {
|
||||||
|
Value value = pop();
|
||||||
|
std::cout << value.to_string() << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Opcode::HALT: {
|
||||||
|
halted_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unknown opcode: " + std::to_string(static_cast<int>(opcode)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// PERFORMANCE PROFILER
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
class Profiler {
|
||||||
|
private:
|
||||||
|
struct InstructionProfile {
|
||||||
|
size_t execution_count;
|
||||||
|
uint64_t total_cycles;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<Opcode, InstructionProfile> profiles_;
|
||||||
|
uint64_t start_cycles_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Profiler() {
|
||||||
|
// Initialize profile names
|
||||||
|
profiles_[Opcode::ADD] = { 0, 0, "ADD" };
|
||||||
|
profiles_[Opcode::SUB] = { 0, 0, "SUB" };
|
||||||
|
profiles_[Opcode::MUL] = { 0, 0, "MUL" };
|
||||||
|
profiles_[Opcode::DIV] = { 0, 0, "DIV" };
|
||||||
|
profiles_[Opcode::CALL] = { 0, 0, "CALL" };
|
||||||
|
profiles_[Opcode::RET] = { 0, 0, "RET" };
|
||||||
|
// Add more as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_measurement() {
|
||||||
|
start_cycles_ = __rdtsc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void record_instruction(Opcode op, size_t ip) {
|
||||||
|
uint64_t end_cycles = __rdtsc();
|
||||||
|
uint64_t cycles = end_cycles - start_cycles_;
|
||||||
|
|
||||||
|
auto& profile = profiles_[op];
|
||||||
|
profile.execution_count++;
|
||||||
|
profile.total_cycles += cycles;
|
||||||
|
|
||||||
|
start_cycles_ = end_cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_report() const {
|
||||||
|
std::cout << "\n=== PERFORMANCE PROFILE ===" << std::endl;
|
||||||
|
std::cout << std::setw(10) << "Instruction"
|
||||||
|
<< std::setw(12) << "Count"
|
||||||
|
<< std::setw(12) << "Total Cycles"
|
||||||
|
<< std::setw(12) << "Avg Cycles" << std::endl;
|
||||||
|
std::cout << std::string(50, '-') << std::endl;
|
||||||
|
|
||||||
|
for (const auto& [opcode, profile] : profiles_) {
|
||||||
|
if (profile.execution_count > 0) {
|
||||||
|
double avg_cycles = static_cast<double>(profile.total_cycles) / profile.execution_count;
|
||||||
|
std::cout << std::setw(10) << profile.name
|
||||||
|
<< std::setw(12) << profile.execution_count
|
||||||
|
<< std::setw(12) << profile.total_cycles
|
||||||
|
<< std::setw(12) << std::fixed << std::setprecision(2) << avg_cycles << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// MEMORY POOL FOR EFFICIENT VALUE ALLOCATION
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
class ValuePool {
|
||||||
|
private:
|
||||||
|
static const size_t POOL_SIZE = 4096;
|
||||||
|
std::vector<Value> pool_;
|
||||||
|
size_t current_index_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ValuePool() : current_index_(0) {
|
||||||
|
pool_.reserve(POOL_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* allocate() {
|
||||||
|
if (current_index_ >= pool_.size()) {
|
||||||
|
pool_.emplace_back();
|
||||||
|
}
|
||||||
|
return &pool_[current_index_++];
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
current_index_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const { return current_index_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// MAIN DEMONSTRATION
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "High-Performance POP VM with JIT Optimizations" << std::endl;
|
||||||
|
std::cout << "=============================================" << std::endl;
|
||||||
|
|
||||||
|
// Create a simple test program: calculate factorial(5)
|
||||||
|
std::vector<uint8_t> test_bytecode = {
|
||||||
|
// PUSH_INT 5 (factorial of 5)
|
||||||
|
0x02, 0x20, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
// PUSH_INT 1 (accumulator)
|
||||||
|
0x02, 0x20, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
// Label: loop_start
|
||||||
|
// DUP2 (duplicate n and acc)
|
||||||
|
0x80,
|
||||||
|
0x02, 0x20, 0x02, 0x00, 0x00, 0x00, // PUSH_INT 2
|
||||||
|
0x80, // DUP to get n again
|
||||||
|
0x42, // CMP_LT (n < 2)
|
||||||
|
|
||||||
|
// JMP_IF to end
|
||||||
|
0x52, 0x0A, 0x00, 0x00, 0x00, // Jump forward 10 bytes if true
|
||||||
|
|
||||||
|
// Multiply acc * n
|
||||||
|
0x22, // MUL
|
||||||
|
|
||||||
|
// Decrement n: PUSH_INT 1, SUB
|
||||||
|
0x02, 0x20, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x21, // SUB
|
||||||
|
|
||||||
|
// Jump back to loop_start
|
||||||
|
0x50, 0xEC, 0xFF, 0xFF, 0xFF, // Jump back 20 bytes
|
||||||
|
|
||||||
|
// Label: end
|
||||||
|
// POP the remaining n, leaving acc on stack
|
||||||
|
0x81, // POP
|
||||||
|
|
||||||
|
// PRINT result
|
||||||
|
0x90,
|
||||||
|
|
||||||
|
// HALT
|
||||||
|
0xA0
|
||||||
|
};
|
||||||
|
|
||||||
|
OptimizedVM vm;
|
||||||
|
|
||||||
|
// Test interpreted execution
|
||||||
|
std::cout << "\n=== INTERPRETED EXECUTION ===" << std::endl;
|
||||||
|
vm.load_bytecode(test_bytecode);
|
||||||
|
vm.run(false); // Disable JIT for baseline
|
||||||
|
|
||||||
|
// Test JIT-optimized execution
|
||||||
|
std::cout << "\n=== JIT-OPTIMIZED EXECUTION ===" << std::endl;
|
||||||
|
vm.load_bytecode(test_bytecode);
|
||||||
|
vm.run(true); // Enable JIT
|
||||||
|
|
||||||
|
// Performance comparison with different optimization levels
|
||||||
|
std::cout << "\n=== PERFORMANCE COMPARISON ===" << std::endl;
|
||||||
|
|
||||||
|
const size_t ITERATIONS = 10000;
|
||||||
|
auto run_benchmark = [&](bool use_jit, const std::string& name) {
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ITERATIONS; ++i) {
|
||||||
|
OptimizedVM bench_vm;
|
||||||
|
bench_vm.load_bytecode(test_bytecode);
|
||||||
|
bench_vm.run(use_jit);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||||
|
|
||||||
|
std::cout << name << ": " << duration.count() << " ms for "
|
||||||
|
<< ITERATIONS << " iterations" << std::endl;
|
||||||
|
};
|
||||||
|
|
||||||
|
run_benchmark(false, "Interpreted ");
|
||||||
|
run_benchmark(true, "JIT ");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
#include "vm_types.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
// Safe memory allocation with overflow checking
|
|
||||||
static void* safe_malloc(size_t size) {
|
|
||||||
if (size == 0 || size > SIZE_MAX / 2) return NULL;
|
|
||||||
void* ptr = malloc(size);
|
|
||||||
if (!ptr) {
|
|
||||||
fprintf(stderr, "Memory allocation failed\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* safe_realloc(void* ptr, size_t size) {
|
|
||||||
if (size == 0 || size > SIZE_MAX / 2) return NULL;
|
|
||||||
void* new_ptr = realloc(ptr, size);
|
|
||||||
if (!new_ptr) {
|
|
||||||
fprintf(stderr, "Memory reallocation failed\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
return new_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize VM with security limits
|
|
||||||
vm_t* vm_create(uint8_t* bytecode, size_t size) {
|
|
||||||
vm_t* vm = safe_malloc(sizeof(vm_t));
|
|
||||||
memset(vm, 0, sizeof(vm_t));
|
|
||||||
|
|
||||||
vm->bytecode = bytecode;
|
|
||||||
vm->bytecode_size = size;
|
|
||||||
vm->ip = 0;
|
|
||||||
vm->halted = false;
|
|
||||||
|
|
||||||
// Security limits
|
|
||||||
vm->max_stack_size = 65536;
|
|
||||||
vm->max_call_depth = 256;
|
|
||||||
vm->current_call_depth = 0;
|
|
||||||
|
|
||||||
return vm;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safe bytecode reading with bounds checking
|
|
||||||
static bool read_u8(vm_t* vm, uint8_t* result) {
|
|
||||||
if (vm->ip >= vm->bytecode_size) return false;
|
|
||||||
*result = vm->bytecode[vm->ip++];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool read_u16(vm_t* vm, uint16_t* result) {
|
|
||||||
if (vm->ip + 2 > vm->bytecode_size) return false;
|
|
||||||
memcpy(result, &vm->bytecode[vm->ip], 2);
|
|
||||||
vm->ip += 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool read_u32(vm_t* vm, uint32_t* result) {
|
|
||||||
if (vm->ip + 4 > vm->bytecode_size) return false;
|
|
||||||
memcpy(result, &vm->bytecode[vm->ip], 4);
|
|
||||||
vm->ip += 4;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool read_i32(vm_t* vm, int32_t* result) {
|
|
||||||
if (vm->ip + 4 > vm->bytecode_size) return false;
|
|
||||||
memcpy(result, &vm->bytecode[vm->ip], 4);
|
|
||||||
vm->ip += 4;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool read_f32(vm_t* vm, float* result) {
|
|
||||||
if (vm->ip + 4 > vm->bytecode_size) return false;
|
|
||||||
memcpy(result, &vm->bytecode[vm->ip], 4);
|
|
||||||
vm->ip += 4;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stack operations with bounds checking
|
|
||||||
static bool stack_push(frame_t* frame, value_t value) {
|
|
||||||
if (frame->stack_size >= frame->stack_capacity) {
|
|
||||||
size_t new_capacity = frame->stack_capacity * 2;
|
|
||||||
if (new_capacity == 0) new_capacity = 16;
|
|
||||||
|
|
||||||
value_t* new_stack = safe_realloc(frame->stack, new_capacity * sizeof(value_t));
|
|
||||||
if (!new_stack) return false;
|
|
||||||
|
|
||||||
frame->stack = new_stack;
|
|
||||||
frame->stack_capacity = new_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame->stack[frame->stack_size++] = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool stack_pop(frame_t* frame, value_t* result) {
|
|
||||||
if (frame->stack_size == 0) return false;
|
|
||||||
*result = frame->stack[--frame->stack_size];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type checking and conversion
|
|
||||||
static bool type_check_binary(value_t a, value_t b, type_code_t* result_type) {
|
|
||||||
// Simple type checking - in real implementation, add proper type promotion
|
|
||||||
if (a.type == b.type) {
|
|
||||||
*result_type = a.type;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t value_to_int(value_t val) {
|
|
||||||
switch (val.type) {
|
|
||||||
case TYPE_I8: return val.data.i8;
|
|
||||||
case TYPE_U8: return val.data.u8;
|
|
||||||
case TYPE_I16: return val.data.i16;
|
|
||||||
case TYPE_U16: return val.data.u16;
|
|
||||||
case TYPE_I32: return val.data.i32;
|
|
||||||
case TYPE_U32: return (int32_t)val.data.u32;
|
|
||||||
case TYPE_BOOL: return val.data.boolean ? 1 : 0;
|
|
||||||
case TYPE_CHAR: return (int32_t)val.data.character;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static float value_to_float(value_t val) {
|
|
||||||
switch (val.type) {
|
|
||||||
case TYPE_F32: return val.data.f32;
|
|
||||||
case TYPE_I32: return (float)val.data.i32;
|
|
||||||
case TYPE_U32: return (float)val.data.u32;
|
|
||||||
default: return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytecode validation
|
|
||||||
bool vm_validate_bytecode(vm_t* vm) {
|
|
||||||
// Check magic number
|
|
||||||
if (vm->bytecode_size < 4 || memcmp(vm->bytecode, "POPC", 4) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add more validation as needed
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute single instruction with full error checking
|
|
||||||
bool vm_execute_instruction(vm_t* vm) {
|
|
||||||
if (vm->halted || vm->ip >= vm->bytecode_size) return false;
|
|
||||||
|
|
||||||
uint8_t opcode;
|
|
||||||
if (!read_u8(vm, &opcode)) return false;
|
|
||||||
|
|
||||||
frame_t* frame = vm->current_frame;
|
|
||||||
if (!frame) return false;
|
|
||||||
|
|
||||||
switch (opcode) {
|
|
||||||
case OP_PUSH_CONST: {
|
|
||||||
uint32_t const_idx;
|
|
||||||
if (!read_u32(vm, &const_idx) || const_idx >= vm->constants_count) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!stack_push(frame, vm->constants[const_idx])) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_PUSH_INT: {
|
|
||||||
uint8_t width;
|
|
||||||
int32_t value;
|
|
||||||
if (!read_u8(vm, &width) || !read_i32(vm, &value)) return false;
|
|
||||||
|
|
||||||
value_t val = { 0 };
|
|
||||||
switch (width) {
|
|
||||||
case 8: val.type = TYPE_I8; val.data.i8 = (int8_t)value; break;
|
|
||||||
case 16: val.type = TYPE_I16; val.data.i16 = (int16_t)value; break;
|
|
||||||
case 32: val.type = TYPE_I32; val.data.i32 = value; break;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
if (!stack_push(frame, val)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_ADD: {
|
|
||||||
value_t a, b;
|
|
||||||
if (!stack_pop(frame, &a) || !stack_pop(frame, &b)) return false;
|
|
||||||
|
|
||||||
type_code_t result_type;
|
|
||||||
if (!type_check_binary(a, b, &result_type)) return false;
|
|
||||||
|
|
||||||
value_t result = { 0 };
|
|
||||||
result.type = result_type;
|
|
||||||
|
|
||||||
if (result_type == TYPE_F32) {
|
|
||||||
result.data.f32 = value_to_float(b) + value_to_float(a);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result.data.i32 = value_to_int(b) + value_to_int(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stack_push(frame, result)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_CMP_EQ: {
|
|
||||||
value_t a, b;
|
|
||||||
if (!stack_pop(frame, &a) || !stack_pop(frame, &b)) return false;
|
|
||||||
|
|
||||||
value_t result = { 0 };
|
|
||||||
result.type = TYPE_BOOL;
|
|
||||||
result.data.boolean = (value_to_int(a) == value_to_int(b));
|
|
||||||
|
|
||||||
if (!stack_push(frame, result)) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_JMP: {
|
|
||||||
int32_t offset;
|
|
||||||
if (!read_i32(vm, &offset)) return false;
|
|
||||||
|
|
||||||
// Check for negative jumps (security)
|
|
||||||
if (offset < 0 && (size_t)(-offset) > vm->ip) return false;
|
|
||||||
if (vm->ip + offset >= vm->bytecode_size) return false;
|
|
||||||
|
|
||||||
vm->ip += offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_PRINT: {
|
|
||||||
value_t val;
|
|
||||||
if (!stack_pop(frame, &val)) return false;
|
|
||||||
|
|
||||||
switch (val.type) {
|
|
||||||
case TYPE_I32: printf("%d\n", val.data.i32); break;
|
|
||||||
case TYPE_F32: printf("%f\n", val.data.f32); break;
|
|
||||||
case TYPE_BOOL: printf("%s\n", val.data.boolean ? "true" : "false"); break;
|
|
||||||
case TYPE_STR: printf("%s\n", val.data.string); break;
|
|
||||||
default: printf("<unknown>\n"); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_HALT:
|
|
||||||
vm->halted = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Unknown opcode: 0x%02x\n", opcode);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main execution loop
|
|
||||||
void vm_execute(vm_t* vm) {
|
|
||||||
while (!vm->halted && vm_execute_instruction(vm)) {
|
|
||||||
// Continue execution
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
void vm_destroy(vm_t* vm) {
|
|
||||||
if (!vm) return;
|
|
||||||
|
|
||||||
// Free constants
|
|
||||||
for (size_t i = 0; i < vm->constants_count; i++) {
|
|
||||||
if (vm->constants[i].type == TYPE_STR && vm->constants[i].data.string) {
|
|
||||||
free(vm->constants[i].data.string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(vm->constants);
|
|
||||||
|
|
||||||
// Free functions
|
|
||||||
free(vm->functions);
|
|
||||||
|
|
||||||
// Free frames (simplified - in real impl, walk call stack)
|
|
||||||
if (vm->current_frame) {
|
|
||||||
free(vm->current_frame->locals);
|
|
||||||
free(vm->current_frame->stack);
|
|
||||||
free(vm->current_frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(vm);
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
#ifndef VM_TYPES_H
|
|
||||||
#define VM_TYPES_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
// Type codes
|
|
||||||
typedef enum {
|
|
||||||
TYPE_I8 = 0x01,
|
|
||||||
TYPE_U8 = 0x02,
|
|
||||||
TYPE_I16 = 0x03,
|
|
||||||
TYPE_U16 = 0x04,
|
|
||||||
TYPE_I32 = 0x05,
|
|
||||||
TYPE_U32 = 0x06,
|
|
||||||
TYPE_F32 = 0x07,
|
|
||||||
TYPE_BOOL = 0x08,
|
|
||||||
TYPE_CHAR = 0x09,
|
|
||||||
TYPE_STR = 0x0A
|
|
||||||
} type_code_t;
|
|
||||||
|
|
||||||
// Opcodes
|
|
||||||
typedef enum {
|
|
||||||
OP_PUSH_CONST = 0x01,
|
|
||||||
OP_PUSH_INT = 0x02,
|
|
||||||
OP_PUSH_FLOAT = 0x03,
|
|
||||||
OP_PUSH_STR = 0x04,
|
|
||||||
OP_LOAD_LOCAL = 0x10,
|
|
||||||
OP_STORE_LOCAL = 0x11,
|
|
||||||
OP_ADD = 0x20,
|
|
||||||
OP_SUB = 0x21,
|
|
||||||
OP_MUL = 0x22,
|
|
||||||
OP_DIV = 0x23,
|
|
||||||
OP_MOD = 0x24,
|
|
||||||
OP_CMP_EQ = 0x40,
|
|
||||||
OP_CMP_NEQ = 0x41,
|
|
||||||
OP_CMP_LT = 0x42,
|
|
||||||
OP_CMP_GT = 0x43,
|
|
||||||
OP_CMP_LE = 0x44,
|
|
||||||
OP_CMP_GE = 0x45,
|
|
||||||
OP_JMP = 0x50,
|
|
||||||
OP_JMP_IF = 0x51,
|
|
||||||
OP_JMP_IF_NOT = 0x52,
|
|
||||||
OP_CALL = 0x60,
|
|
||||||
OP_RET = 0x61,
|
|
||||||
OP_DUP = 0x80,
|
|
||||||
OP_POP = 0x81,
|
|
||||||
OP_PRINT = 0x90,
|
|
||||||
OP_HALT = 0xA0
|
|
||||||
} opcode_t;
|
|
||||||
|
|
||||||
// Value union with type safety
|
|
||||||
typedef union {
|
|
||||||
int8_t i8;
|
|
||||||
uint8_t u8;
|
|
||||||
int16_t i16;
|
|
||||||
uint16_t u16;
|
|
||||||
int32_t i32;
|
|
||||||
uint32_t u32;
|
|
||||||
float f32;
|
|
||||||
bool boolean;
|
|
||||||
char character;
|
|
||||||
char* string;
|
|
||||||
} value_data_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
type_code_t type;
|
|
||||||
value_data_t data;
|
|
||||||
} value_t;
|
|
||||||
|
|
||||||
// Function definition
|
|
||||||
typedef struct {
|
|
||||||
uint32_t name_index;
|
|
||||||
uint8_t arg_count;
|
|
||||||
uint8_t local_count;
|
|
||||||
uint16_t reserved;
|
|
||||||
uint32_t code_size;
|
|
||||||
uint32_t code_offset;
|
|
||||||
} function_t;
|
|
||||||
|
|
||||||
// Call frame
|
|
||||||
typedef struct frame {
|
|
||||||
struct frame* prev;
|
|
||||||
uint32_t return_ip;
|
|
||||||
value_t* locals;
|
|
||||||
value_t* stack;
|
|
||||||
size_t stack_size;
|
|
||||||
size_t stack_capacity;
|
|
||||||
size_t locals_count;
|
|
||||||
} frame_t;
|
|
||||||
|
|
||||||
// Virtual machine state
|
|
||||||
typedef struct {
|
|
||||||
uint8_t* bytecode;
|
|
||||||
size_t bytecode_size;
|
|
||||||
uint32_t ip;
|
|
||||||
|
|
||||||
value_t* constants;
|
|
||||||
size_t constants_count;
|
|
||||||
|
|
||||||
function_t* functions;
|
|
||||||
size_t functions_count;
|
|
||||||
|
|
||||||
frame_t* current_frame;
|
|
||||||
bool halted;
|
|
||||||
|
|
||||||
// Security settings
|
|
||||||
size_t max_stack_size;
|
|
||||||
size_t max_call_depth;
|
|
||||||
size_t current_call_depth;
|
|
||||||
} vm_t;
|
|
||||||
|
|
||||||
// Function declarations
|
|
||||||
vm_t* vm_create(uint8_t* bytecode, size_t size);
|
|
||||||
bool vm_validate_bytecode(vm_t* vm);
|
|
||||||
bool vm_execute_instruction(vm_t* vm);
|
|
||||||
void vm_execute(vm_t* vm);
|
|
||||||
void vm_destroy(vm_t* vm);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
fun main() {
|
fun main() {
|
||||||
u8 testint = 255;
|
U8 testint = 2;
|
||||||
print(testint);
|
print(testint);
|
||||||
|
|
||||||
|
for(U8 i = 0; i < 10; i++) {
|
||||||
|
testint = testint + 1;
|
||||||
|
print(testint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user