package build

import (
	"strconv"

	"git.akyoto.dev/cli/q/src/build/asm"
	"git.akyoto.dev/cli/q/src/build/config"
	"git.akyoto.dev/cli/q/src/build/cpu"
	"git.akyoto.dev/cli/q/src/build/token"
	"git.akyoto.dev/cli/q/src/errors"
)

// TokenToRegister moves a token into a register.
// It only works with identifiers, numbers and strings.
func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
	switch t.Kind {
	case token.Identifier:
		name := t.Text()
		constant, exists := f.definitions[name]

		if exists {
			if config.Verbose {
				f.Logf("constant %s = %s", constant.Name, constant.Value)
			}

			return f.ExpressionToRegister(constant.Value, register)
		}

		variable, exists := f.variables[name]

		if !exists {
			return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position)
		}

		if register != variable.Register {
			f.assembler.RegisterRegister(asm.MOVE, register, variable.Register)
		}

		f.useVariable(variable)
		return nil

	case token.Number:
		value := t.Text()
		n, err := strconv.Atoi(value)

		if err != nil {
			return err
		}

		f.assembler.RegisterNumber(asm.MOVE, register, n)
		return nil

	case token.String:
		return errors.New(errors.NotImplemented, f.File, t.Position)

	default:
		return errors.New(errors.InvalidExpression, f.File, t.Position)
	}
}