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
|
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
|
## Platforms
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ func (f *Function) CompileAssignDivision(expr *expression.Expression) error {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if expr.Token.Kind == token.Define {
|
if expr.Token.Kind == token.Define {
|
||||||
quotientVariable, err = f.Define(variables.Children[0])
|
quotientVariable, err = f.NewVariable(variables.Children[0])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
remainderVariable, err = f.Define(variables.Children[1])
|
remainderVariable, err = f.NewVariable(variables.Children[1])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -13,7 +13,7 @@ func (f *Function) CompileDefinition(node *ast.Define) error {
|
|||||||
right := node.Expression.Children[1]
|
right := node.Expression.Children[1]
|
||||||
|
|
||||||
if left.IsLeaf() {
|
if left.IsLeaf() {
|
||||||
variable, err := f.Define(left)
|
variable, err := f.NewVariable(left)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"git.urbach.dev/cli/q/src/errors"
|
"git.urbach.dev/cli/q/src/errors"
|
||||||
"git.urbach.dev/cli/q/src/eval"
|
"git.urbach.dev/cli/q/src/eval"
|
||||||
"git.urbach.dev/cli/q/src/expression"
|
"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/token"
|
||||||
"git.urbach.dev/cli/q/src/types"
|
"git.urbach.dev/cli/q/src/types"
|
||||||
)
|
)
|
||||||
@ -29,14 +30,15 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
|||||||
to *expression.Expression
|
to *expression.Expression
|
||||||
)
|
)
|
||||||
|
|
||||||
|
counter = f.NewRegister()
|
||||||
|
defer f.FreeRegister(counter)
|
||||||
|
|
||||||
switch loop.Head.Token.Kind {
|
switch loop.Head.Token.Kind {
|
||||||
case token.Define:
|
case token.Define:
|
||||||
from = loop.Head.Children[1].Children[0]
|
from = loop.Head.Children[1].Children[0]
|
||||||
to = loop.Head.Children[1].Children[1]
|
to = loop.Head.Children[1].Children[1]
|
||||||
|
|
||||||
case token.Range:
|
case token.Range:
|
||||||
counter = f.NewRegister()
|
|
||||||
defer f.FreeRegister(counter)
|
|
||||||
from = loop.Head.Children[0]
|
from = loop.Head.Children[0]
|
||||||
to = loop.Head.Children[1]
|
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)
|
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) {
|
switch value := value.(type) {
|
||||||
case *eval.Number:
|
case *eval.Number:
|
||||||
f.AddLabel(label)
|
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))
|
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)
|
f.Jump(asm.JGE, labelEnd)
|
||||||
err = f.CompileAST(loop.Body)
|
err = f.CompileAST(loop.Body)
|
||||||
f.RegisterNumber(asm.ADD, counter, 1)
|
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 {
|
return left.EachLeaf(func(leaf *expression.Expression) error {
|
||||||
variable, err := f.Define(leaf)
|
variable, err := f.NewVariable(leaf)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -8,8 +8,8 @@ import (
|
|||||||
"git.urbach.dev/cli/q/src/token"
|
"git.urbach.dev/cli/q/src/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define defines a new variable.
|
// NewVariable creates a new variable.
|
||||||
func (f *Function) Define(leaf *expression.Expression) (*scope.Variable, error) {
|
func (f *Function) NewVariable(leaf *expression.Expression) (*scope.Variable, error) {
|
||||||
name := leaf.Token.Text(f.File.Bytes)
|
name := leaf.Token.Text(f.File.Bytes)
|
||||||
variable := f.VariableByName(name)
|
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-lifetime", 0},
|
||||||
{"loop-in-loop", 0},
|
{"loop-in-loop", 0},
|
||||||
{"for", 0},
|
{"for", 0},
|
||||||
|
{"factorial", 0},
|
||||||
{"fibonacci", 0},
|
{"fibonacci", 0},
|
||||||
{"memory-free", 0},
|
{"memory-free", 0},
|
||||||
{"out-of-memory", 0},
|
{"out-of-memory", 0},
|
||||||
|
Reference in New Issue
Block a user