This commit is contained in:
parent
f1457af6be
commit
e5baba175b
12 changed files with 221 additions and 4 deletions
|
@ -10,6 +10,7 @@ type Build struct {
|
||||||
Files []string
|
Files []string
|
||||||
Arch Arch
|
Arch Arch
|
||||||
OS OS
|
OS OS
|
||||||
|
Dry bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executable returns the path to the executable.
|
// Executable returns the path to the executable.
|
||||||
|
|
|
@ -8,7 +8,7 @@ func Exec(args []string) int {
|
||||||
|
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "build":
|
case "build":
|
||||||
return build(args[1:])
|
return _build(args[1:])
|
||||||
|
|
||||||
case "run":
|
case "run":
|
||||||
return run(args[1:])
|
return run(args[1:])
|
||||||
|
|
|
@ -11,6 +11,15 @@ func TestExec(t *testing.T) {
|
||||||
assert.Equal(t, cli.Exec(nil), 2)
|
assert.Equal(t, cli.Exec(nil), 2)
|
||||||
assert.Equal(t, cli.Exec([]string{"_"}), 2)
|
assert.Equal(t, cli.Exec([]string{"_"}), 2)
|
||||||
assert.Equal(t, cli.Exec([]string{"build"}), 0)
|
assert.Equal(t, cli.Exec([]string{"build"}), 0)
|
||||||
assert.Equal(t, cli.Exec([]string{"run"}), 0)
|
assert.Equal(t, cli.Exec([]string{"build", "--invalid-parameter"}), 2)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--invalid-parameter"}), 2)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--dry"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--dry", "--os", "linux"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--dry", "--os", "mac"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--dry", "--os", "windows"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--dry", "--arch", "arm"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello", "--dry", "--arch", "x86"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"build", "../../examples/hello/hello.q", "--dry"}), 0)
|
||||||
assert.Equal(t, cli.Exec([]string{"help"}), 0)
|
assert.Equal(t, cli.Exec([]string{"help"}), 0)
|
||||||
|
assert.Equal(t, cli.Exec([]string{"run"}), 0)
|
||||||
}
|
}
|
|
@ -1,6 +1,94 @@
|
||||||
package cli
|
package cli
|
||||||
|
|
||||||
// build parses the arguments and creates a build.
|
import (
|
||||||
func build(args []string) int {
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/build"
|
||||||
|
"git.urbach.dev/cli/q/src/compiler"
|
||||||
|
"git.urbach.dev/cli/q/src/scanner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// _build parses the arguments and creates a build.
|
||||||
|
func _build(args []string) int {
|
||||||
|
b, err := newBuildFromArgs(args)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return exit(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = compiler.Compile(scanner.Scan(b))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return exit(err)
|
||||||
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newBuildFromArgs creates a new build with the given arguments.
|
||||||
|
func newBuildFromArgs(args []string) (*build.Build, error) {
|
||||||
|
b := build.New()
|
||||||
|
|
||||||
|
for i := 0; i < len(args); i++ {
|
||||||
|
switch args[i] {
|
||||||
|
case "--arch":
|
||||||
|
i++
|
||||||
|
|
||||||
|
if i >= len(args) {
|
||||||
|
return b, &expectedParameterError{Parameter: "arch"}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch args[i] {
|
||||||
|
case "arm":
|
||||||
|
b.Arch = build.ARM
|
||||||
|
case "x86":
|
||||||
|
b.Arch = build.X86
|
||||||
|
default:
|
||||||
|
return b, &invalidValueError{Value: args[i], Parameter: "arch"}
|
||||||
|
}
|
||||||
|
|
||||||
|
case "--dry":
|
||||||
|
b.Dry = true
|
||||||
|
|
||||||
|
case "--os":
|
||||||
|
i++
|
||||||
|
|
||||||
|
if i >= len(args) {
|
||||||
|
return b, &expectedParameterError{Parameter: "os"}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch args[i] {
|
||||||
|
case "linux":
|
||||||
|
b.OS = build.Linux
|
||||||
|
case "mac":
|
||||||
|
b.OS = build.Mac
|
||||||
|
case "windows":
|
||||||
|
b.OS = build.Windows
|
||||||
|
default:
|
||||||
|
return b, &invalidValueError{Value: args[i], Parameter: "os"}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if strings.HasPrefix(args[i], "-") {
|
||||||
|
return b, &unknownParameterError{Parameter: args[i]}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Files = append(b.Files, args[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.OS == build.UnknownOS {
|
||||||
|
return b, &invalidValueError{Value: runtime.GOOS, Parameter: "os"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Arch == build.UnknownArch {
|
||||||
|
return b, &invalidValueError{Value: runtime.GOARCH, Parameter: "arch"}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b.Files) == 0 {
|
||||||
|
b.Files = append(b.Files, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
34
src/cli/errors.go
Normal file
34
src/cli/errors.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// expectedParameterError is created when a command line parameter is missing.
|
||||||
|
type expectedParameterError struct {
|
||||||
|
Parameter string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (err *expectedParameterError) Error() string {
|
||||||
|
return fmt.Sprintf("Expected parameter '%s'", err.Parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalidValueError is created when a parameter has an invalid value.
|
||||||
|
type invalidValueError struct {
|
||||||
|
Value string
|
||||||
|
Parameter string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (err *invalidValueError) Error() string {
|
||||||
|
return fmt.Sprintf("Invalid value '%s' for parameter '%s'", err.Value, err.Parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unknownParameterError is created when a command line parameter is not recognized.
|
||||||
|
type unknownParameterError struct {
|
||||||
|
Parameter string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (err *unknownParameterError) Error() string {
|
||||||
|
return fmt.Sprintf("Unknown parameter '%s'", err.Parameter)
|
||||||
|
}
|
30
src/cli/exit.go
Normal file
30
src/cli/exit.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// exit returns the exit code depending on the error type.
|
||||||
|
func exit(err error) int {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|
||||||
|
var (
|
||||||
|
exit *exec.ExitError
|
||||||
|
expectedParameter *expectedParameterError
|
||||||
|
unknownParameter *unknownParameterError
|
||||||
|
invalidValue *invalidValueError
|
||||||
|
)
|
||||||
|
|
||||||
|
if errors.As(err, &exit) {
|
||||||
|
return exit.ExitCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err, &expectedParameter) || errors.As(err, &unknownParameter) || errors.As(err, &invalidValue) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
8
src/compiler/Compile.go
Normal file
8
src/compiler/Compile.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package compiler
|
||||||
|
|
||||||
|
import "git.urbach.dev/cli/q/src/scanner"
|
||||||
|
|
||||||
|
// Compile waits for the scan to finish and compiles all functions.
|
||||||
|
func Compile(scan scanner.Result) (Result, error) {
|
||||||
|
return Result{}, nil
|
||||||
|
}
|
16
src/compiler/Compile_test.go
Normal file
16
src/compiler/Compile_test.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package compiler_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/build"
|
||||||
|
"git.urbach.dev/cli/q/src/compiler"
|
||||||
|
"git.urbach.dev/cli/q/src/scanner"
|
||||||
|
"git.urbach.dev/go/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCompile(t *testing.T) {
|
||||||
|
b := build.New("../../examples/hello")
|
||||||
|
_, err := compiler.Compile(scanner.Scan(b))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
4
src/compiler/Result.go
Normal file
4
src/compiler/Result.go
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package compiler
|
||||||
|
|
||||||
|
// Result contains everything we need to write an executable file to disk.
|
||||||
|
type Result struct{}
|
4
src/scanner/Result.go
Normal file
4
src/scanner/Result.go
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package scanner
|
||||||
|
|
||||||
|
// Result contains everything the compiler needs to start a build.
|
||||||
|
type Result struct{}
|
10
src/scanner/Scan.go
Normal file
10
src/scanner/Scan.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package scanner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.urbach.dev/cli/q/src/build"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Scan scans all the files included in the build.
|
||||||
|
func Scan(b *build.Build) Result {
|
||||||
|
return Result{}
|
||||||
|
}
|
13
src/scanner/Scan_test.go
Normal file
13
src/scanner/Scan_test.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package scanner_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/build"
|
||||||
|
"git.urbach.dev/cli/q/src/scanner"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestScan(t *testing.T) {
|
||||||
|
b := build.New("../../examples/hello")
|
||||||
|
scanner.Scan(b)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue