diff --git a/src/core/compileAssign.go b/src/core/compileAssign.go index 6119b7f..37e751b 100644 --- a/src/core/compileAssign.go +++ b/src/core/compileAssign.go @@ -33,6 +33,10 @@ func (f *Function) compileAssign(node *ast.Assign) error { return err } + if f.IsIdentified(rightValue) { + rightValue = f.copy(rightValue, ssa.Source(right.Source())) + } + if node.Expression.Token.Kind == token.Assign { f.Block().Identify(name, rightValue) return nil diff --git a/src/core/compileDefinition.go b/src/core/compileDefinition.go index 7a0fefa..0f4ca08 100644 --- a/src/core/compileDefinition.go +++ b/src/core/compileDefinition.go @@ -29,7 +29,6 @@ func (f *Function) compileDefinition(node *ast.Define) error { return err } - block := f.Block() structure, isStructType := value.Type().(*types.Struct) // If the value we got was a value that is stored in a variable, @@ -37,7 +36,7 @@ func (f *Function) compileDefinition(node *ast.Define) error { // We want to assure that every named variable creates a copy of // another named variable instead of using the cached value itself // because it could lead to incorrect optimizations. - if !isStructType && block.IsIdentified(value) { + if !isStructType && f.IsIdentified(value) { value = f.copy(value, ssa.Source(right.Source())) } diff --git a/src/ssa/IR.go b/src/ssa/IR.go index a0e3752..c349591 100644 --- a/src/ssa/IR.go +++ b/src/ssa/IR.go @@ -47,6 +47,17 @@ func (f *IR) Finalize() { } } +// IsIdentified returns true if the value can be obtained from one of the identifiers. +func (f *IR) IsIdentified(value Value) bool { + for _, block := range f.Blocks { + if block.IsIdentified(value) { + return true + } + } + + return false +} + // Values yields on each value. func (f *IR) Values(yield func(int, Value) bool) { index := 0 diff --git a/tests/fibonacci.q b/tests/fibonacci.q new file mode 100644 index 0000000..425f00e --- /dev/null +++ b/tests/fibonacci.q @@ -0,0 +1,26 @@ +main() { + loop i := 0..10 { + assert fib1(i) == fib2(i) + } +} + +fib1(n int) -> int { + b := 0 + c := 1 + + loop 0..n { + a := b + b = c + c = a + b + } + + return b +} + +fib2(n int) -> int { + if n <= 1 { + return n + } + + return fib2(n - 1) + fib2(n - 2) +} \ No newline at end of file