Preserve Gotlin semantics across packages
This commit is contained in:
parent
5b30e49486
commit
acb42a5702
10 changed files with 525 additions and 34 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
|
@ -32,6 +33,10 @@ func runBuild(args []string) {
|
|||
fs := flag.NewFlagSet("build", flag.ExitOnError)
|
||||
srcOnly := fs.Bool("src", false, "emit Go source instead of building an executable")
|
||||
outPath := fs.String("o", "", "output file path")
|
||||
metadataOutput := fs.String("metadata-output", "", "write Gotlin package metadata")
|
||||
metadataPackage := fs.String("metadata-package", "", "import path recorded in package metadata")
|
||||
var metadataInputs stringListFlag
|
||||
fs.Var(&metadataInputs, "metadata", "Gotlin package metadata dependency (repeatable)")
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "usage: gotlinc build [-src] [-o output] <input.gt>")
|
||||
}
|
||||
|
|
@ -48,7 +53,7 @@ func runBuild(args []string) {
|
|||
}
|
||||
|
||||
inputPath := fs.Arg(0)
|
||||
goSrc := compileFiles(fs.Args(), !*srcOnly)
|
||||
goSrc := compileFilesWithMetadata(fs.Args(), !*srcOnly, metadataInputs, *metadataOutput, *metadataPackage)
|
||||
|
||||
if *srcOnly {
|
||||
if *outPath == "" {
|
||||
|
|
@ -117,6 +122,10 @@ func compileFile(inputPath string, forceMain bool) string {
|
|||
}
|
||||
|
||||
func compileFiles(inputPaths []string, forceMain bool) string {
|
||||
return compileFilesWithMetadata(inputPaths, forceMain, nil, "", "")
|
||||
}
|
||||
|
||||
func compileFilesWithMetadata(inputPaths []string, forceMain bool, metadataPaths []string, metadataOutput, metadataPackage string) string {
|
||||
program := &lang.Program{}
|
||||
var firstSource string
|
||||
for _, inputPath := range inputPaths {
|
||||
|
|
@ -146,12 +155,27 @@ func compileFiles(inputPaths []string, forceMain bool) string {
|
|||
firstSource = string(src)
|
||||
}
|
||||
}
|
||||
metadata := loadMetadata(metadataPaths)
|
||||
if metadataOutput != "" {
|
||||
packageMetadata, err := lang.BuildPackageMetadata(program, metadataPackage)
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
encoded, err := json.MarshalIndent(packageMetadata, "", " ")
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
encoded = append(encoded, '\n')
|
||||
if err := os.WriteFile(metadataOutput, encoded, 0o644); err != nil {
|
||||
fail(err)
|
||||
}
|
||||
}
|
||||
var goSrc []byte
|
||||
var err error
|
||||
if forceMain {
|
||||
goSrc, err = lang.GenerateGoMain(program)
|
||||
goSrc, err = lang.GenerateGoMainWithMetadata(program, metadata)
|
||||
} else {
|
||||
goSrc, err = lang.GenerateGo(program)
|
||||
goSrc, err = lang.GenerateGoWithMetadata(program, metadata)
|
||||
}
|
||||
if err != nil {
|
||||
fail(err)
|
||||
|
|
@ -162,6 +186,30 @@ func compileFiles(inputPaths []string, forceMain bool) string {
|
|||
return string(goSrc)
|
||||
}
|
||||
|
||||
type stringListFlag []string
|
||||
|
||||
func (values *stringListFlag) String() string { return strings.Join(*values, ",") }
|
||||
func (values *stringListFlag) Set(value string) error { *values = append(*values, value); return nil }
|
||||
|
||||
func loadMetadata(paths []string) []*lang.PackageMetadata {
|
||||
metadata := make([]*lang.PackageMetadata, 0, len(paths))
|
||||
for _, path := range paths {
|
||||
body, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
var item lang.PackageMetadata
|
||||
if err := json.Unmarshal(body, &item); err != nil {
|
||||
fail(fmt.Errorf("load metadata %s: %w", path, err))
|
||||
}
|
||||
if item.Version != lang.PackageMetadataVersion {
|
||||
fail(fmt.Errorf("metadata %s uses unsupported version %d", path, item.Version))
|
||||
}
|
||||
metadata = append(metadata, &item)
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
func buildExecutable(goSrc string, outputPath string) error {
|
||||
tmpFile, err := os.CreateTemp("", "gotlinc-build-*.go")
|
||||
if err != nil {
|
||||
|
|
@ -202,7 +250,7 @@ func normalizeBuildArgs(args []string) ([]string, error) {
|
|||
switch {
|
||||
case arg == "-src":
|
||||
flags = append(flags, arg)
|
||||
case arg == "-o":
|
||||
case arg == "-o" || arg == "-metadata" || arg == "-metadata-output" || arg == "-metadata-package":
|
||||
if i+1 >= len(args) {
|
||||
return nil, fmt.Errorf("missing value for -o")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue