diff options
Diffstat (limited to 'comp/dump.go')
| -rw-r--r-- | comp/dump.go | 76 |
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 +} |
