From ff0f679d6a19cf36490a24de118db44f7a624dce Mon Sep 17 00:00:00 2001 From: lunfardo314 Date: Mon, 13 May 2024 13:00:10 +0300 Subject: [PATCH] wip serde --- library.go | 65 +++++++++++++++++++++++++++++++++++++++++++++--------- serde.go | 23 ++++++++++++++----- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/library.go b/library.go index 6563872..293f8c8 100644 --- a/library.go +++ b/library.go @@ -136,10 +136,24 @@ func (lib *Library) PrintLibraryStats() { // embedShort embeds short-callable function into the library func (lib *Library) embedShort(sym string, requiredNumPar int, evalFun EvalFunction) byte { - Assert(lib.numEmbeddedShort < MaxNumEmbeddedShort, "too many embedded short functions") - Assert(!lib.existsFunction(sym), "EasyFL: !existsFunction(sym)") - Assert(requiredNumPar <= 15, "EasyFL: can't be more than 15 parameters") - Assert(requiredNumPar >= 0, "EasyFL: short embedded vararg functions are not allowed") + ret, err := lib.embedShortErr(sym, requiredNumPar, evalFun) + AssertNoError(err) + return ret +} + +func (lib *Library) embedShortErr(sym string, requiredNumPar int, evalFun EvalFunction) (byte, error) { + if lib.numEmbeddedShort >= MaxNumEmbeddedShort { + return 0, fmt.Errorf("EasyFL: too many embedded short functions") + } + if lib.existsFunction(sym) { + return 0, fmt.Errorf("EasyFL: repeating function '%s'", sym) + } + if requiredNumPar > 15 { + return 0, fmt.Errorf("EasyFL: can't be more than 15 parameters") + } + if requiredNumPar < 0 { + return 0, fmt.Errorf("EasyFL: short embedded vararg functions are not allowed") + } if traceYN { evalFun = wrapWithTracing(evalFun, sym) } @@ -162,13 +176,26 @@ func (lib *Library) embedShort(sym string, requiredNumPar int, evalFun EvalFunct AssertNoError(err) Assert(len(codeBytes) == 1, "expected short code") } - return byte(dscr.funCode) + return byte(dscr.funCode), nil } func (lib *Library) embedLong(sym string, requiredNumPar int, evalFun EvalFunction) uint16 { - Assert(lib.numEmbeddedLong < MaxNumEmbeddedLong, "too many embedded long functions") - Assert(!lib.existsFunction(sym), "!existsFunction(sym)") - Assert(requiredNumPar <= 15, "can't be more than 15 parameters") + ret, err := lib.embedLongErr(sym, requiredNumPar, evalFun) + AssertNoError(err) + return ret +} + +func (lib *Library) embedLongErr(sym string, requiredNumPar int, evalFun EvalFunction) (uint16, error) { + if lib.numEmbeddedLong > MaxNumEmbeddedLong { + return 0, fmt.Errorf("EasyFL: too many embedded long functions") + } + if lib.existsFunction(sym) { + return 0, fmt.Errorf("EasyFL: repeating function '%s'", sym) + } + if requiredNumPar > 15 { + return 0, fmt.Errorf("EasyFL: can't be more than 15 parameters") + } + if traceYN { evalFun = wrapWithTracing(evalFun, sym) } @@ -191,19 +218,35 @@ func (lib *Library) embedLong(sym string, requiredNumPar int, evalFun EvalFuncti AssertNoError(err) Assert(len(codeBytes) == 2, "expected long code") } - return dscr.funCode + return dscr.funCode, nil } func (lib *Library) EmbedShort(funList ...*EmbedFunction) { + err := lib.EmbedShortErr(funList...) + AssertNoError(err) +} + +func (lib *Library) EmbedShortErr(funList ...*EmbedFunction) (err error) { for _, fun := range funList { - lib.embedShort(fun.Sym, fun.RequiredNumPar, fun.EvalFun) + if _, err = lib.embedShortErr(fun.Sym, fun.RequiredNumPar, fun.EvalFun); err != nil { + return + } } + return } func (lib *Library) EmbedLong(funList ...*EmbedFunction) { + err := lib.EmbedLongErr(funList...) + AssertNoError(err) +} + +func (lib *Library) EmbedLongErr(funList ...*EmbedFunction) (err error) { for _, fun := range funList { - lib.embedLong(fun.Sym, fun.RequiredNumPar, fun.EvalFun) + if _, err = lib.embedLongErr(fun.Sym, fun.RequiredNumPar, fun.EvalFun); err != nil { + return + } } + return } func (lib *Library) Extend(funList ...*ExtendFunction) { diff --git a/serde.go b/serde.go index db70f71..4da2ff4 100644 --- a/serde.go +++ b/serde.go @@ -18,6 +18,14 @@ func (lib *Library) LibraryHash() [32]byte { func (lib *Library) libraryBytes() []byte { var buf bytes.Buffer + var uint16Bin [2]byte + binary.BigEndian.PutUint16(uint16Bin[:], lib.numEmbeddedShort) + buf.Write(uint16Bin[:]) + binary.BigEndian.PutUint16(uint16Bin[:], lib.numEmbeddedLong) + buf.Write(uint16Bin[:]) + binary.BigEndian.PutUint16(uint16Bin[:], lib.numExtended) + buf.Write(uint16Bin[:]) + funCodes := make([]uint16, 0, len(lib.funByFunCode)) for funCode := range lib.funByFunCode { funCodes = append(funCodes, funCode) @@ -31,6 +39,11 @@ func (lib *Library) libraryBytes() []byte { return buf.Bytes() } +func (lib *Library) fromBytes(data []byte) (err error) { + // TODO + return nil +} + func (fd *funDescriptor) write(w io.Writer) { var uint16Bin [2]byte // fun code @@ -81,12 +94,12 @@ func (fd *funDescriptor) read(r io.Reader, lib *Library) error { } } else { // embedded - var fi *funInfo - if fi, err = lib.functionByName(fd.sym); err != nil { - return err + var sym string + if fd.evalFun, fd.requiredNumParams, sym, err = lib.functionByCode(fd.funCode); err != nil { + return fmt.Errorf("can't find embedded function '%s' with code %d: %w", fd.sym, fd.funCode, err) } - if fd.evalFun, fd.requiredNumParams, _, err = lib.functionByCode(fi.FunCode); err != nil { - return fmt.Errorf("can't find embedded function '%s' with code %d: %w", fi.Sym, fi.FunCode, err) + if sym != fd.sym { + return fmt.Errorf("embedded function with code %d: expected name '%s', got '%s'", fd.funCode, fd.sym, sym) } } return nil