This commit is contained in:
parent
c2b8db238e
commit
735246bd38
36 changed files with 129 additions and 111 deletions
|
@ -3,12 +3,13 @@ package compiler
|
|||
import (
|
||||
"git.urbach.dev/cli/q/src/build"
|
||||
"git.urbach.dev/cli/q/src/errors"
|
||||
"git.urbach.dev/cli/q/src/scanner"
|
||||
)
|
||||
|
||||
// Compile waits for the scan to finish and compiles all functions.
|
||||
func Compile(b *build.Build) (Result, error) {
|
||||
result := Result{}
|
||||
all, err := scan(b)
|
||||
all, err := scanner.Scan(b)
|
||||
|
||||
if err != nil {
|
||||
return result, err
|
||||
|
@ -18,7 +19,6 @@ func Compile(b *build.Build) (Result, error) {
|
|||
return result, errors.NoInputFiles
|
||||
}
|
||||
|
||||
// Resolve the types
|
||||
for _, function := range all.Functions {
|
||||
err := function.ResolveTypes()
|
||||
|
||||
|
@ -27,8 +27,6 @@ func Compile(b *build.Build) (Result, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Parallel compilation
|
||||
compileFunctions(all.Functions)
|
||||
|
||||
return result, nil
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package compiler
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/build"
|
||||
"git.urbach.dev/cli/q/src/core"
|
||||
"git.urbach.dev/cli/q/src/fs"
|
||||
"git.urbach.dev/cli/q/src/scanner"
|
||||
)
|
||||
|
||||
func scan(b *build.Build) (*core.Environment, error) {
|
||||
functions, files, errs := scanner.Scan(b)
|
||||
|
||||
all := &core.Environment{
|
||||
Files: make([]*fs.File, 0, 8),
|
||||
Functions: make(map[string]*core.Function, 32),
|
||||
}
|
||||
|
||||
for functions != nil || files != nil || errs != nil {
|
||||
select {
|
||||
case f, ok := <-functions:
|
||||
if !ok {
|
||||
functions = nil
|
||||
continue
|
||||
}
|
||||
|
||||
all.Functions[f.String()] = f
|
||||
|
||||
case file, ok := <-files:
|
||||
if !ok {
|
||||
files = nil
|
||||
continue
|
||||
}
|
||||
|
||||
all.Files = append(all.Files, file)
|
||||
|
||||
case err, ok := <-errs:
|
||||
if !ok {
|
||||
errs = nil
|
||||
continue
|
||||
}
|
||||
|
||||
return all, err
|
||||
}
|
||||
}
|
||||
|
||||
return all, nil
|
||||
}
|
|
@ -3,7 +3,7 @@ package errors
|
|||
var (
|
||||
ExpectedFunctionDefinition = &String{"Expected function definition"}
|
||||
ExpectedPackageName = &String{"Expected package name"}
|
||||
InvalidDefinition = &String{"Invalid definition"}
|
||||
InvalidFunctionDefinition = &String{"Invalid function definition"}
|
||||
MissingBlockStart = &String{"Missing '{'"}
|
||||
MissingBlockEnd = &String{"Missing '}'"}
|
||||
MissingGroupStart = &String{"Missing '('"}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
// Scan scans all the files included in the build.
|
||||
func Scan(b *build.Build) (<-chan *core.Function, <-chan *fs.File, <-chan error) {
|
||||
func Scan(b *build.Build) (*core.Environment, error) {
|
||||
s := scanner{
|
||||
functions: make(chan *core.Function),
|
||||
files: make(chan *fs.File),
|
||||
|
@ -23,5 +23,38 @@ func Scan(b *build.Build) (<-chan *core.Function, <-chan *fs.File, <-chan error)
|
|||
close(s.errors)
|
||||
}()
|
||||
|
||||
return s.functions, s.files, s.errors
|
||||
all := &core.Environment{
|
||||
Files: make([]*fs.File, 0, 8),
|
||||
Functions: make(map[string]*core.Function, 32),
|
||||
}
|
||||
|
||||
for s.functions != nil || s.files != nil || s.errors != nil {
|
||||
select {
|
||||
case f, ok := <-s.functions:
|
||||
if !ok {
|
||||
s.functions = nil
|
||||
continue
|
||||
}
|
||||
|
||||
all.Functions[f.String()] = f
|
||||
|
||||
case file, ok := <-s.files:
|
||||
if !ok {
|
||||
s.files = nil
|
||||
continue
|
||||
}
|
||||
|
||||
all.Files = append(all.Files, file)
|
||||
|
||||
case err, ok := <-s.errors:
|
||||
if !ok {
|
||||
s.errors = nil
|
||||
continue
|
||||
}
|
||||
|
||||
return all, err
|
||||
}
|
||||
}
|
||||
|
||||
return all, nil
|
||||
}
|
|
@ -4,70 +4,24 @@ import (
|
|||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/build"
|
||||
"git.urbach.dev/cli/q/src/core"
|
||||
"git.urbach.dev/cli/q/src/fs"
|
||||
"git.urbach.dev/cli/q/src/scanner"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestScanDirectory(t *testing.T) {
|
||||
b := build.New("testdata")
|
||||
functions, files, errors := scanner.Scan(b)
|
||||
err := consume(t, functions, files, errors)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestScanFile(t *testing.T) {
|
||||
b := build.New("testdata/file.q")
|
||||
functions, files, errors := scanner.Scan(b)
|
||||
err := consume(t, functions, files, errors)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestScanNotExisting(t *testing.T) {
|
||||
func TestNotExisting(t *testing.T) {
|
||||
b := build.New("_")
|
||||
functions, files, errors := scanner.Scan(b)
|
||||
err := consume(t, functions, files, errors)
|
||||
_, err := scanner.Scan(b)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestMultiPlatform(t *testing.T) {
|
||||
b := build.New("testdata/platforms")
|
||||
_, err := scanner.Scan(b)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestScanHelloExample(t *testing.T) {
|
||||
b := build.New("../../examples/hello")
|
||||
functions, files, errors := scanner.Scan(b)
|
||||
err := consume(t, functions, files, errors)
|
||||
_, err := scanner.Scan(b)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func consume(t *testing.T, functions <-chan *core.Function, files <-chan *fs.File, errors <-chan error) error {
|
||||
var lastError error
|
||||
|
||||
for functions != nil || files != nil || errors != nil {
|
||||
select {
|
||||
case function, ok := <-functions:
|
||||
if !ok {
|
||||
functions = nil
|
||||
continue
|
||||
}
|
||||
|
||||
t.Log(function)
|
||||
|
||||
case file, ok := <-files:
|
||||
if !ok {
|
||||
files = nil
|
||||
continue
|
||||
}
|
||||
|
||||
t.Log(file)
|
||||
|
||||
case err, ok := <-errors:
|
||||
if !ok {
|
||||
errors = nil
|
||||
continue
|
||||
}
|
||||
|
||||
lastError = err
|
||||
}
|
||||
}
|
||||
|
||||
return lastError
|
||||
}
|
50
src/scanner/errors_test.go
Normal file
50
src/scanner/errors_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package scanner_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/build"
|
||||
"git.urbach.dev/cli/q/src/errors"
|
||||
"git.urbach.dev/cli/q/src/scanner"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
var errs = []struct {
|
||||
File string
|
||||
ExpectedError error
|
||||
}{
|
||||
{"ExpectedFunctionDefinition.q", errors.ExpectedFunctionDefinition},
|
||||
{"ExpectedPackageName.q", errors.ExpectedPackageName},
|
||||
{"InvalidCharacter.q", &errors.InvalidCharacter{Character: "@"}},
|
||||
{"InvalidCharacter2.q", &errors.InvalidCharacter{Character: "@"}},
|
||||
{"InvalidCharacter3.q", &errors.InvalidCharacter{Character: "@"}},
|
||||
{"InvalidCharacter4.q", &errors.InvalidCharacter{Character: "+++"}},
|
||||
{"InvalidFunctionDefinition.q", errors.InvalidFunctionDefinition},
|
||||
{"InvalidTopLevel.q", &errors.InvalidTopLevel{Instruction: "123"}},
|
||||
{"InvalidTopLevel2.q", &errors.InvalidTopLevel{Instruction: "\"Hello\""}},
|
||||
{"InvalidTopLevel3.q", &errors.InvalidTopLevel{Instruction: "+"}},
|
||||
{"MissingBlockEnd.q", errors.MissingBlockEnd},
|
||||
{"MissingBlockEnd2.q", errors.MissingBlockEnd},
|
||||
{"MissingBlockStart.q", errors.MissingBlockStart},
|
||||
{"MissingGroupEnd.q", errors.MissingGroupEnd},
|
||||
{"MissingGroupStart.q", errors.MissingGroupStart},
|
||||
{"MissingParameter.q", errors.MissingParameter},
|
||||
{"MissingParameter2.q", errors.MissingParameter},
|
||||
{"MissingParameter3.q", errors.MissingParameter},
|
||||
{"MissingType.q", errors.MissingType},
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
for _, test := range errs {
|
||||
name := strings.TrimSuffix(test.File, ".q")
|
||||
|
||||
t.Run(name, func(t *testing.T) {
|
||||
b := build.New(filepath.Join("testdata", "errors", test.File))
|
||||
_, err := scanner.Scan(b)
|
||||
assert.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), test.ExpectedError.Error())
|
||||
})
|
||||
}
|
||||
}
|
|
@ -60,7 +60,7 @@ func scanSignature(file *fs.File, tokens token.List, i int, delimiter token.Kind
|
|||
}
|
||||
|
||||
if paramsStart == -1 {
|
||||
return nil, i, errors.New(errors.InvalidDefinition, file, tokens[i].Position)
|
||||
return nil, i, errors.New(errors.InvalidFunctionDefinition, file, tokens[i].Position)
|
||||
}
|
||||
|
||||
return nil, i, nil
|
||||
|
@ -71,7 +71,7 @@ func scanSignature(file *fs.File, tokens token.List, i int, delimiter token.Kind
|
|||
continue
|
||||
}
|
||||
|
||||
return nil, i, errors.New(errors.InvalidDefinition, file, tokens[i].Position)
|
||||
return nil, i, errors.New(errors.InvalidFunctionDefinition, file, tokens[i].Position)
|
||||
}
|
||||
|
||||
// Return type
|
||||
|
|
1
src/scanner/testdata/errors/ExpectedFunctionDefinition.q
vendored
Normal file
1
src/scanner/testdata/errors/ExpectedFunctionDefinition.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main()
|
1
src/scanner/testdata/errors/ExpectedPackageName.q
vendored
Normal file
1
src/scanner/testdata/errors/ExpectedPackageName.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
import
|
1
src/scanner/testdata/errors/InvalidCharacter.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidCharacter.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
@
|
1
src/scanner/testdata/errors/InvalidCharacter2.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidCharacter2.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main@
|
1
src/scanner/testdata/errors/InvalidCharacter3.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidCharacter3.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main()@
|
4
src/scanner/testdata/errors/InvalidCharacter4.q
vendored
Normal file
4
src/scanner/testdata/errors/InvalidCharacter4.q
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
main() {
|
||||
x := 123 +++ 456
|
||||
syscall(60, x)
|
||||
}
|
3
src/scanner/testdata/errors/InvalidCondition.q
vendored
Normal file
3
src/scanner/testdata/errors/InvalidCondition.q
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
main() {
|
||||
if 42 {}
|
||||
}
|
3
src/scanner/testdata/errors/InvalidExpression.q
vendored
Normal file
3
src/scanner/testdata/errors/InvalidExpression.q
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
main() {
|
||||
syscall(+, -, *, /)
|
||||
}
|
1
src/scanner/testdata/errors/InvalidFunctionDefinition.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidFunctionDefinition.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main
|
1
src/scanner/testdata/errors/InvalidTopLevel.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidTopLevel.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
123
|
1
src/scanner/testdata/errors/InvalidTopLevel2.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidTopLevel2.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
"Hello"
|
1
src/scanner/testdata/errors/InvalidTopLevel3.q
vendored
Normal file
1
src/scanner/testdata/errors/InvalidTopLevel3.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
+
|
1
src/scanner/testdata/errors/MissingBlockEnd.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingBlockEnd.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main(){
|
3
src/scanner/testdata/errors/MissingBlockEnd2.q
vendored
Normal file
3
src/scanner/testdata/errors/MissingBlockEnd2.q
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
main() {
|
||||
loop {
|
||||
}
|
1
src/scanner/testdata/errors/MissingBlockStart.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingBlockStart.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main()}
|
1
src/scanner/testdata/errors/MissingGroupEnd.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingGroupEnd.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main(
|
1
src/scanner/testdata/errors/MissingGroupStart.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingGroupStart.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
main)
|
1
src/scanner/testdata/errors/MissingParameter.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingParameter.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
f(,) {}
|
1
src/scanner/testdata/errors/MissingParameter2.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingParameter2.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
f(a int,) -> int { return a }
|
1
src/scanner/testdata/errors/MissingParameter3.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingParameter3.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
f(,a int) {}
|
1
src/scanner/testdata/errors/MissingType.q
vendored
Normal file
1
src/scanner/testdata/errors/MissingType.q
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
f(a) {}
|
Loading…
Add table
Add a link
Reference in a new issue