-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathengine.go
More file actions
145 lines (132 loc) · 4.3 KB
/
Copy pathengine.go
File metadata and controls
145 lines (132 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package lc
import (
"context"
"errors"
"fmt"
"github.com/pt-main/lc/engine"
"github.com/pt-main/lc/engine/core"
"github.com/pt-main/lc/parsing/byteParsing"
"github.com/pt-main/lc/parsing/stringParsing"
"github.com/pt-main/lc/public"
lcplugin "github.com/pt-main/lc/tooling/plugin"
)
type EngineUniversal struct {
Plugins *lcplugin.PluginManager
Type public.EngineType
StringEngine engine.EngineInterface[string, string, stringParsing.ParsedNode]
ByteEngine engine.EngineInterface[int, []byte, byteParsing.ParsedBytes]
opcode_counter int
Context context.Context
CtxCancelCause context.CancelCauseFunc
ended bool
}
func (e *EngineUniversal) ProcessStringWithCtx(input string, ctx context.Context) error {
if err := e.CheckEnded(); err != nil {
return err
}
if e.Type != public.StringEngineType {
return errors.New("Can't process string in byte engine")
}
uep, _ := e.GetUEP()
uep.Context = ctx
return e.StringEngine.Process(input)
}
func (e *EngineUniversal) ProcessBytesWithCtx(input []byte, ctx context.Context) error {
if err := e.CheckEnded(); err != nil {
return err
}
if e.Type != public.ByteEngineType {
return errors.New("Can't process bytes in string engine")
}
uep, _ := e.GetUEP()
uep.Context = ctx
return e.ByteEngine.Process(input)
}
// ProcessString feeds a string input into the engine.
// It works only for engines of type StringEngineType; otherwise returns an error.
// Internally triggers the parse and call events, executing registered handlers.
func (e *EngineUniversal) ProcessString(input string) error {
return e.ProcessStringWithCtx(input, context.Background())
}
// ProcessBytes feeds a byte slice into the engine (ByteEngineType only).
// The input is passed via scope under key "input_[]byte", then parsed and processed.
func (e *EngineUniversal) ProcessBytes(input []byte) error {
return e.ProcessBytesWithCtx(input, context.Background())
}
func (e *EngineUniversal) GetUEP() (*core.UniversalEngineParams, error) {
if err := e.CheckEnded(); err != nil {
return nil, err
}
if e.Type == public.StringEngineType {
return e.StringEngine.GetUep(), nil
}
return e.ByteEngine.GetUep(), nil
}
// NewCommandByte registers a bytecode command identified by an opcode.
// If opcode == -1, the engine automatically assigns the next available opcode.
// handler receives (*ByteEngine, ParsedBytes).
func (e *EngineUniversal) NewCommandByte(
opcode int, handler core.CommandType[engine.ByteEngineInterface, byteParsing.ParsedBytes], name string,
autoByecodeIdxShift bool,
) error {
if err := e.CheckEnded(); err != nil {
return err
}
if e.Type != public.ByteEngineType {
return errors.New("Can't add byte command to string engine")
}
finalOpcode := opcode
if opcode == -1 {
finalOpcode = e.opcode_counter
e.opcode_counter++
} else {
e.opcode_counter = max(opcode, e.opcode_counter)
}
e.ByteEngine.NewCommand(finalOpcode, handler, &core.SimpleInput{
Input: name,
Option: &core.Option{Flags: []string{engine.AutoshiftNewCommandFlag}},
})
return nil
}
// NewCommandString registers a text-based command in a StringEngine.
// cmdSwitch is the command name (e.g., "print"). handler must have signature
// func([]interface{}) error where arguments are (*StringEngine, ParsedNode).
// doc is an optional documentation string.
func (e *EngineUniversal) NewCommandString(
cmdSwitch string, handler core.CommandType[engine.StringEngineInterface, stringParsing.ParsedNode], doc string,
) error {
if err := e.CheckEnded(); err != nil {
return err
}
if e.Type != public.StringEngineType {
return errors.New("Can't add string command to byte engine")
}
e.StringEngine.NewCommand(cmdSwitch, handler, &core.SimpleInput{
Input: doc,
})
return nil
}
// End - function for stop engines lifecycle.
func (e *EngineUniversal) End() (err error) {
err = e.CheckEnded()
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("[%v] Panic recovered: %v. ", err, r)
}
}()
if e.Plugins != nil {
err = fmt.Errorf("[%v] Plugin error: %v. ", err, e.Plugins.End())
}
if e.Context.Err() != nil {
e.CtxCancelCause(fmt.Errorf("EngineUniversal: lifecycle end."))
}
e.ByteEngine = nil
e.StringEngine = nil
return
}
func (e *EngineUniversal) CheckEnded() (err error) {
if e.ended {
err = fmt.Errorf("EngineUniversal: lifecycle ended.")
}
return err
}