Started parsing of //go:embed pragmas

This commit is contained in:
BCG
2021-07-19 20:12:44 -04:00
parent b40703e986
commit 778c79cc85
10 changed files with 116 additions and 1 deletions
+10
View File
@@ -8,6 +8,7 @@ import (
"go/constant"
"go/token"
"go/types"
"log"
"math/bits"
"path/filepath"
"sort"
@@ -693,6 +694,7 @@ func (c *compilerContext) getDIFile(filename string) llvm.Metadata {
// createPackage builds the LLVM IR for all types, methods, and global variables
// in the given package.
func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package) {
println("called create package:", pkg.Pkg.Name())
// Sort by position, so that the order of the functions in the IR matches
// the order of functions in the source file. This is useful for testing,
// for example.
@@ -758,6 +760,13 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
case *ssa.Global:
// Global variable.
info := c.getGlobalInfo(member)
if strings.TrimSpace(info.embeds) != "" {
embeds, err := parseGoEmbed(info.embeds)
if err != nil {
log.Fatal(err)
}
fmt.Printf("file embed found at %v: %v\n", info.linkName, embeds)
}
global := c.getGlobal(member)
if !info.extern {
global.SetInitializer(llvm.ConstNull(global.Type().ElementType()))
@@ -766,6 +775,7 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
global.SetSection(info.section)
}
}
}
}
}
+70
View File
@@ -0,0 +1,70 @@
package compiler
import (
"fmt"
"strconv"
"strings"
"unicode"
"unicode/utf8"
)
// parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
// It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
// Copied from https://github.com/golang/go/blob/219fe9d547d09d3de1b024c6c8b8314dd0bf12e4/src/cmd/compile/internal/noder/noder.go#L1717-L1776
func parseGoEmbed(args string) ([]string, error) {
var list []string
for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
var path string
Switch:
switch args[0] {
default:
i := len(args)
for j, c := range args {
if unicode.IsSpace(c) {
i = j
break
}
}
path = args[:i]
args = args[i:]
case '`':
i := strings.Index(args[1:], "`")
if i < 0 {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
}
path = args[1 : 1+i]
args = args[1+i+1:]
case '"':
i := 1
for ; i < len(args); i++ {
if args[i] == '\\' {
i++
continue
}
if args[i] == '"' {
q, err := strconv.Unquote(args[:i+1])
if err != nil {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
}
path = q
args = args[i+1:]
break Switch
}
}
if i >= len(args) {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
}
}
if args != "" {
r, _ := utf8.DecodeRuneInString(args)
if !unicode.IsSpace(r) {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
}
}
list = append(list, path)
}
return list, nil
}
+4
View File
@@ -331,6 +331,7 @@ type globalInfo struct {
extern bool // go:extern
align int // go:align
section string // go:section
embeds string // go:embed
}
// loadASTComments loads comments on globals from the AST, for use later in the
@@ -448,6 +449,9 @@ func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) {
if len(parts) == 2 {
info.section = parts[1]
}
case "//go:embed":
raw := strings.TrimPrefix(comment.Text, "//go:embed")
info.embeds += " " + raw
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
module github.com/tinygo-org/tinygo
go 1.13
go 1.16
require (
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
+21
View File
@@ -0,0 +1,21 @@
package main
import (
"embed"
"log"
)
//go:embed file1.txt file2.txt
//go:embed file3.txt
var files embed.FS
func main() {
println(msg)
contents, err := files.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, c := range contents {
println("file:", c.Name())
}
}
+1
View File
@@ -0,0 +1 @@
file 1
+1
View File
@@ -0,0 +1 @@
file 2
+1
View File
@@ -0,0 +1 @@
file 3
+1
View File
@@ -0,0 +1 @@
hello world!
+6
View File
@@ -0,0 +1,6 @@
package main
import _ "embed"
//go:embed message.txt
var msg string