Added more tests
This commit is contained in:
@ -33,7 +33,7 @@ You can take a look at the [examples](../examples).
|
||||
go run gotest.tools/gotestsum@latest
|
||||
```
|
||||
|
||||
This will run over 350 [tests](../tests) in various categories.
|
||||
This will run over 400 [tests](../tests) in various categories.
|
||||
|
||||
## Platforms
|
||||
|
||||
|
@ -24,13 +24,13 @@ func (f *Function) CompileAssignDivision(expr *expression.Expression) error {
|
||||
)
|
||||
|
||||
if expr.Token.Kind == token.Define {
|
||||
quotientVariable, err = f.Define(variables.Children[0])
|
||||
quotientVariable, err = f.NewVariable(variables.Children[0])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
remainderVariable, err = f.Define(variables.Children[1])
|
||||
remainderVariable, err = f.NewVariable(variables.Children[1])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -13,7 +13,7 @@ func (f *Function) CompileDefinition(node *ast.Define) error {
|
||||
right := node.Expression.Children[1]
|
||||
|
||||
if left.IsLeaf() {
|
||||
variable, err := f.Define(left)
|
||||
variable, err := f.NewVariable(left)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"git.urbach.dev/cli/q/src/errors"
|
||||
"git.urbach.dev/cli/q/src/eval"
|
||||
"git.urbach.dev/cli/q/src/expression"
|
||||
"git.urbach.dev/cli/q/src/scope"
|
||||
"git.urbach.dev/cli/q/src/token"
|
||||
"git.urbach.dev/cli/q/src/types"
|
||||
)
|
||||
@ -29,14 +30,15 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
||||
to *expression.Expression
|
||||
)
|
||||
|
||||
counter = f.NewRegister()
|
||||
defer f.FreeRegister(counter)
|
||||
|
||||
switch loop.Head.Token.Kind {
|
||||
case token.Define:
|
||||
from = loop.Head.Children[1].Children[0]
|
||||
to = loop.Head.Children[1].Children[1]
|
||||
|
||||
case token.Range:
|
||||
counter = f.NewRegister()
|
||||
defer f.FreeRegister(counter)
|
||||
from = loop.Head.Children[0]
|
||||
to = loop.Head.Children[1]
|
||||
|
||||
@ -60,20 +62,6 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
||||
return errors.New(&errors.TypeMismatch{Encountered: value.Type().Name(), Expected: types.AnyInt.Name()}, f.File, to.Token.Position)
|
||||
}
|
||||
|
||||
scope := f.PushScope(loop.Body, f.File.Bytes)
|
||||
scope.InLoop = true
|
||||
|
||||
if loop.Head.Token.Kind == token.Define {
|
||||
variable, err := f.Define(loop.Head.Children[0])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counter = variable.Value.Register
|
||||
f.AddVariable(variable)
|
||||
}
|
||||
|
||||
switch value := value.(type) {
|
||||
case *eval.Number:
|
||||
f.AddLabel(label)
|
||||
@ -95,6 +83,29 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
||||
panic(fmt.Errorf("%s: not implemented: %v", f.UniqueName, value))
|
||||
}
|
||||
|
||||
loopScope := f.PushScope(loop.Body, f.File.Bytes)
|
||||
loopScope.InLoop = true
|
||||
|
||||
if loop.Head.Token.Kind == token.Define {
|
||||
leaf := loop.Head.Children[0]
|
||||
name := leaf.Token.Text(f.File.Bytes)
|
||||
variable := f.VariableByName(name)
|
||||
|
||||
if variable != nil {
|
||||
return errors.New(&errors.VariableAlreadyExists{Name: name}, f.File, leaf.Token.Position)
|
||||
}
|
||||
|
||||
variable = &scope.Variable{
|
||||
Name: name,
|
||||
Value: eval.Register{
|
||||
Register: counter,
|
||||
Alive: ast.Count(loop.Body, f.File.Bytes, token.Identifier, name),
|
||||
},
|
||||
}
|
||||
|
||||
f.AddVariable(variable)
|
||||
}
|
||||
|
||||
f.Jump(asm.JGE, labelEnd)
|
||||
err = f.CompileAST(loop.Body)
|
||||
f.RegisterNumber(asm.ADD, counter, 1)
|
||||
|
@ -15,7 +15,7 @@ func (f *Function) MultiDefine(left *expression.Expression, right *expression.Ex
|
||||
}
|
||||
|
||||
return left.EachLeaf(func(leaf *expression.Expression) error {
|
||||
variable, err := f.Define(leaf)
|
||||
variable, err := f.NewVariable(leaf)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
"git.urbach.dev/cli/q/src/token"
|
||||
)
|
||||
|
||||
// Define defines a new variable.
|
||||
func (f *Function) Define(leaf *expression.Expression) (*scope.Variable, error) {
|
||||
// NewVariable creates a new variable.
|
||||
func (f *Function) NewVariable(leaf *expression.Expression) (*scope.Variable, error) {
|
||||
name := leaf.Token.Text(f.File.Bytes)
|
||||
variable := f.VariableByName(name)
|
||||
|
23
tests/programs/factorial.q
Normal file
23
tests/programs/factorial.q
Normal file
@ -0,0 +1,23 @@
|
||||
main() {
|
||||
for i := 0..10 {
|
||||
assert fac1(i) == fac2(i)
|
||||
}
|
||||
}
|
||||
|
||||
fac1(n int) -> int {
|
||||
x := 1
|
||||
|
||||
for i := 1..n+1 {
|
||||
x = x * i
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
fac2(n int) -> int {
|
||||
if n <= 1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
return n * fac2(n - 1)
|
||||
}
|
@ -62,6 +62,7 @@ var programs = []struct {
|
||||
{"loop-lifetime", 0},
|
||||
{"loop-in-loop", 0},
|
||||
{"for", 0},
|
||||
{"factorial", 0},
|
||||
{"fibonacci", 0},
|
||||
{"memory-free", 0},
|
||||
{"out-of-memory", 0},
|
||||
|
Reference in New Issue
Block a user