summaryrefslogtreecommitdiff
path: root/comp/dump.go
diff options
context:
space:
mode:
Diffstat (limited to 'comp/dump.go')
-rw-r--r--comp/dump.go76
1 files changed, 76 insertions, 0 deletions
diff --git a/comp/dump.go b/comp/dump.go
new file mode 100644
index 0000000..865216b
--- /dev/null
+++ b/comp/dump.go
@@ -0,0 +1,76 @@
+package comp
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// Dump represents the state of a data dump.
+type Dump struct {
+ Values []*DumpValue
+}
+
+// DumpValue is a value of a dump state.
+type DumpValue struct {
+ Index int
+ Name string
+ Kind int
+ Type string
+ Value any
+}
+
+// Dump creates a snapshot of the execution state of global variables.
+// This method is specifically implemented in the Compiler to minimize the coupling between
+// the dump format and other components. By situating the dump logic in the Compiler,
+// it relies solely on the program being executed and the indexing algorithm used for ordering variables
+// (currently, this is an integer that corresponds to the order of variables in the program).
+// This design choice allows the Virtual Machine (VM) to evolve its memory management strategies
+// without compromising backward compatibility with dumps generated by previous versions.
+func (c *Compiler) Dump() *Dump {
+ dict := c.symbolsByIndex()
+ dv := make([]*DumpValue, len(c.Data))
+ for i, d := range c.Data {
+ e := dict[i]
+ dv[i] = &DumpValue{
+ Index: e.Index,
+ Name: e.name,
+ Kind: int(e.Kind),
+ Type: e.Type.Name,
+ Value: d.Interface(),
+ }
+ }
+ return &Dump{Values: dv}
+}
+
+// ApplyDump sets previously saved dump, restoring the state of global variables.
+func (c *Compiler) ApplyDump(d *Dump) error {
+ dict := c.symbolsByIndex()
+ for _, dv := range d.Values {
+ // do all the checks to be sure we are applying the correct values
+ e, ok := dict[dv.Index]
+ if !ok {
+ return fmt.Errorf("entry not found on index %d", dv.Index)
+ }
+
+ if dv.Name != e.name ||
+ dv.Type != e.Type.Name ||
+ dv.Kind != int(e.Kind) {
+ return fmt.Errorf("entry with index %d does not match with provided entry. "+
+ "dumpValue: %s, %s, %d. memoryValue: %s, %s, %d",
+ dv.Index,
+ dv.Name, dv.Type, dv.Kind,
+ e.name, e.Type, e.Kind)
+ }
+
+ if dv.Index >= len(c.Data) {
+ return fmt.Errorf("index (%d) bigger than memory (%d)", dv.Index, len(c.Data))
+ }
+
+ if !c.Data[dv.Index].CanSet() {
+ return fmt.Errorf("value %v cannot be set", dv.Value)
+ }
+
+ c.Data[dv.Index].Set(reflect.ValueOf(dv.Value))
+ }
+ return nil
+}