From bffc031ea83c7176aac3d3828de0060c6630140c Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 6 Jan 2026 19:02:29 +0100 Subject: fix: correct and simplify parsing of expressions. The expressions were parsed from right to left, and it was incorrect and cumbersome. Now they are processed from left to right, with a simpler and correct handling of precedence rules. The vm function call syntax has been changed to set the function before the input arguments on the stack, as to follow the declaring order in languages. --- comp/dump.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 comp/dump.go (limited to 'comp/dump.go') 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 +} -- cgit v1.2.3