q/src/core/EvaluateToken.go
2025-03-13 16:57:13 +01:00

97 lines
1.8 KiB
Go

package core
import (
"encoding/binary"
"fmt"
"git.urbach.dev/cli/q/src/asm"
"git.urbach.dev/cli/q/src/errors"
"git.urbach.dev/cli/q/src/eval"
"git.urbach.dev/cli/q/src/token"
"git.urbach.dev/cli/q/src/types"
)
// EvaluateToken evaluates a single token.
func (f *Function) EvaluateToken(t token.Token) (eval.Value, error) {
switch t.Kind {
case token.Identifier:
name := t.Text(f.File.Bytes)
if name == "true" {
value := &eval.Number{
Typ: types.Bool,
Number: 1,
}
return value, nil
}
if name == "false" {
value := &eval.Number{
Typ: types.Bool,
Number: 0,
}
return value, nil
}
variable := f.VariableByName(name)
if variable != nil {
f.UseVariable(variable)
return &variable.Value, nil
}
uniqueName := fmt.Sprintf("%s.%s", f.Package, name)
function, exists := f.All.Functions[uniqueName]
if exists {
f.Dependencies = append(f.Dependencies, function)
value := &eval.Label{
Typ: types.AnyPointer,
Label: asm.Label{
Name: function.UniqueName,
Type: asm.FunctionLabel,
},
}
return value, nil
}
return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
case token.Number, token.Rune:
number, err := f.ToNumber(t)
if err != nil {
return nil, err
}
value := &eval.Number{
Typ: types.AnyInt,
Number: number,
}
return value, nil
case token.String:
data := t.Bytes(f.File.Bytes)
data = String(data)
slice := make([]byte, len(data)+8+1)
binary.LittleEndian.PutUint64(slice, uint64(len(data)))
copy(slice[8:], data)
label := f.AddBytes(slice)
value := &eval.Label{
Typ: types.String,
Label: label,
}
return value, nil
}
return nil, errors.New(errors.InvalidExpression, f.File, t.Position)
}