func DecodeProgram()

in internal/compile/serial.go [213:292]


func DecodeProgram(data []byte) (_ *Program, err error) {
	if len(data) < len(magic) {
		return nil, fmt.Errorf("not a compiled module: no magic number")
	}
	if got := string(data[:4]); got != magic {
		return nil, fmt.Errorf("not a compiled module: got magic number %q, want %q",
			got, magic)
	}
	defer func() {
		if x := recover(); x != nil {
			debugpkg.PrintStack()
			err = fmt.Errorf("internal error while decoding program: %v", x)
		}
	}()

	offset := binary.LittleEndian.Uint32(data[4:8])
	d := decoder{
		p: data[8:offset],
		s: append([]byte(nil), data[offset:]...), // allocate a copy, which will persist
	}

	if v := d.int(); v != Version {
		return nil, fmt.Errorf("version mismatch: read %d, want %d", v, Version)
	}

	filename := d.string()
	d.filename = &filename

	loads := d.bindings()

	names := make([]string, d.int())
	for i := range names {
		names[i] = d.string()
	}

	// constants
	constants := make([]interface{}, d.int())
	for i := range constants {
		var c interface{}
		switch d.int() {
		case 0:
			c = d.string()
		case 1:
			c = Bytes(d.string())
		case 2:
			c = d.int64()
		case 3:
			c = math.Float64frombits(d.uint64())
		case 4:
			c, _ = new(big.Int).SetString(d.string(), 10)
		}
		constants[i] = c
	}

	globals := d.bindings()
	toplevel := d.function()
	funcs := make([]*Funcode, d.int())
	for i := range funcs {
		funcs[i] = d.function()
	}

	prog := &Program{
		Loads:     loads,
		Names:     names,
		Constants: constants,
		Globals:   globals,
		Functions: funcs,
		Toplevel:  toplevel,
	}
	toplevel.Prog = prog
	for _, f := range funcs {
		f.Prog = prog
	}

	if len(d.p)+len(d.s) > 0 {
		return nil, fmt.Errorf("internal error: unconsumed data during decoding")
	}

	return prog, nil
}