Added variables and variable setting

Just string variables for name
This commit is contained in:
Leon Mika 2024-04-11 20:58:59 +10:00
parent 1506692198
commit 41a4d7fd25
6 changed files with 54 additions and 2 deletions

View file

@ -12,6 +12,7 @@ type astLiteral struct {
type astCmdArg struct {
Literal *astLiteral `parser:"@@"`
Var *string `parser:"| '$' @Ident"`
Sub *astPipeline `parser:"| '(' @@ ')'"`
}

View file

@ -25,6 +25,23 @@ func echoBuiltin(ctx context.Context, args invocationArgs) (object, error) {
return asStream(line.String()), nil
}
func setBuiltin(ctx context.Context, args invocationArgs) (object, error) {
if err := args.expectArgn(2); err != nil {
return nil, err
}
name, err := args.stringArg(0)
if err != nil {
return nil, err
}
newVal := args.args[1]
// TODO: if the value is a stream, consume the stream and save it as a list
args.ec.setVar(name, newVal)
return newVal, nil
}
func toUpperBuiltin(ctx context.Context, inStream stream, args invocationArgs) (object, error) {
// Handle args
return mapFilterStream{

View file

@ -8,6 +8,7 @@ type evalCtx struct {
parent *evalCtx
currentStream stream
commands map[string]invokable
vars map[string]object
}
func (ec *evalCtx) withCurrentStream(s stream) *evalCtx {
@ -25,6 +26,27 @@ func (ec *evalCtx) addCmd(name string, inv invokable) {
ec.commands[name] = inv
}
func (ec *evalCtx) setVar(name string, val object) {
if ec.vars == nil {
ec.vars = make(map[string]object)
}
ec.vars[name] = val
}
func (ec *evalCtx) getVar(name string) (object, bool) {
if ec.vars == nil {
return nil, false
}
if v, ok := ec.vars[name]; ok {
return v, true
} else if ec.parent != nil {
return ec.parent.getVar(name)
}
return nil, false
}
func (ec *evalCtx) lookupCmd(name string) (invokable, error) {
for e := ec; e != nil; e = e.parent {
if e.commands == nil {

View file

@ -45,9 +45,11 @@ func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, ast *astCmd) (objec
return nil, err
}
invArgs := invocationArgs{ec: ec, args: args}
if ec.currentStream != nil {
if si, ok := cmd.(streamInvokable); ok {
return si.invokeWithStream(ctx, ec.currentStream, invocationArgs{args: args})
return si.invokeWithStream(ctx, ec.currentStream, invArgs)
} else {
if err := ec.currentStream.close(); err != nil {
return nil, err
@ -55,13 +57,19 @@ func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, ast *astCmd) (objec
}
}
return cmd.invoke(ctx, invocationArgs{args: args})
return cmd.invoke(ctx, invArgs)
}
func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (object, error) {
switch {
case n.Literal != nil:
return e.evalLiteral(ctx, ec, n.Literal)
case n.Var != nil:
v, ok := ec.getVar(*n.Var)
if !ok {
return nil, fmt.Errorf("unknown variable %s", *n.Var)
}
return v, nil
case n.Sub != nil:
return e.evalSub(ctx, ec, n.Sub)
}

View file

@ -13,11 +13,14 @@ type Inst struct {
func New() *Inst {
rootEC := evalCtx{}
rootEC.addCmd("echo", invokableFunc(echoBuiltin))
rootEC.addCmd("set", invokableFunc(setBuiltin))
rootEC.addCmd("toUpper", invokableStreamFunc(toUpperBuiltin))
rootEC.addCmd("cat", invokableFunc(catBuiltin))
rootEC.addCmd("testTimebomb", invokableStreamFunc(errorTestBuiltin))
rootEC.setVar("hello", strObject("world"))
return &Inst{
rootEC: &rootEC,
}

View file

@ -17,6 +17,7 @@ func (s strObject) String() string {
}
type invocationArgs struct {
ec *evalCtx
args []object
}