diff --git a/src/build/core/ExpressionToRegister.go b/src/build/core/ExpressionToRegister.go index ef69a6f..fade8b8 100644 --- a/src/build/core/ExpressionToRegister.go +++ b/src/build/core/ExpressionToRegister.go @@ -27,7 +27,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp right := node.Children[1] final := register - if OverwritesRegister(right, register) { + if f.UsesRegister(right, register) { register = f.cpu.MustFindFree(f.cpu.General) } diff --git a/src/build/core/OverwritesRegister.go b/src/build/core/OverwritesRegister.go deleted file mode 100644 index ce950f8..0000000 --- a/src/build/core/OverwritesRegister.go +++ /dev/null @@ -1,11 +0,0 @@ -package core - -import ( - "git.akyoto.dev/cli/q/src/build/cpu" - "git.akyoto.dev/cli/q/src/build/expression" -) - -// OverwritesRegister returns true if evaluating the expression would overwrite the given register. -func OverwritesRegister(expr *expression.Expression, register cpu.Register) bool { - return !expr.IsLeaf() -} diff --git a/src/build/core/UsesRegister.go b/src/build/core/UsesRegister.go new file mode 100644 index 0000000..5090f63 --- /dev/null +++ b/src/build/core/UsesRegister.go @@ -0,0 +1,47 @@ +package core + +import ( + "git.akyoto.dev/cli/q/src/build/ast" + "git.akyoto.dev/cli/q/src/build/cpu" + "git.akyoto.dev/cli/q/src/build/expression" + "git.akyoto.dev/cli/q/src/build/token" +) + +// UsesRegister returns true if evaluating the expression would write or read the given register. +func (f *Function) UsesRegister(expr *expression.Expression, register cpu.Register) bool { + if expr.IsLeaf() { + if expr.Token.Kind == token.Number { + return false + } + + name := expr.Token.Text() + variable := f.variables[name] + return register == variable.Register + } + + if ast.IsFunctionCall(expr) { + if register == f.cpu.Output[0] { + return true + } + + for i, parameter := range expr.Children[1:] { + if register == f.cpu.Input[i] { + return true + } + + if f.UsesRegister(parameter, register) { + return true + } + } + + return false + } + + for _, child := range expr.Children { + if f.UsesRegister(child, register) { + return true + } + } + + return false +}