This is an initial pass at property binding. For all stack instantiations, we must verify that the set of properties supplied are correct. We also must remember the bound property information so that code-generation has all of the information it needs to generate correct code (including capability refs). This entails: * Ensuring required properties are provided. * Expanding missing properties that have Default values. * Type-checking that supplied properties are of the right type. * Expanding property values into AST literal nodes. To do this requires a third AST pass in the semantic analysis part of the compiler. In the 1st pass, dependencies aren't even known yet; in the 2nd pass, dependencies have not yet been bound; therefore, we need a 3rd pass, which can depend on the full binding information for the transitive closure of AST nodes and dependencies to have been populated with types. There are a few loose ends in here: * We don't yet validate top-level stack properties. * We don't yet validate top-level stack base type properties. * We don't yet support complex schema property types. * We don't yet support even "simple" complex property types, like `[ string ]`. * We don't yet support strongly typed capability property types (just `service`). That said, I am going to turn to writing a few tests for the basic cases, and then resume to finishing this afterwards (tracked by marapongo/mu#25).
46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
// Copyright 2016 Marapongo, Inc. All rights reserved.
|
|
|
|
package ast
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/marapongo/mu/pkg/util"
|
|
)
|
|
|
|
// NameDelimiter is what delimits Namespace and Name parts.
|
|
const NameDelimiter = "/"
|
|
|
|
var NameRegexp = regexp.MustCompile(NameRegexps)
|
|
var NameRegexps = "(" + NamePartRegexps + "\\" + NameDelimiter + ")*" + NamePartRegexps
|
|
var NamePartRegexps = "[A-Za-z_][A-Za-z0-9_]*"
|
|
|
|
// IsName checks whether a string is a legal Name.
|
|
func IsName(s string) bool {
|
|
return NameRegexp.FindString(s) == s
|
|
}
|
|
|
|
// AsName converts a given string to a Name, asserting its validity.
|
|
func AsName(s string) Name {
|
|
util.AssertMF(NameRegexp.MatchString(s), "Expected string '%v' to be a name (%v)", s, NameRegexps)
|
|
return Name(s)
|
|
}
|
|
|
|
// Simple extracts the name portion of a Name (dropping any Namespace).
|
|
func (nm Name) Simple() Name {
|
|
ix := strings.LastIndex(string(nm), NameDelimiter)
|
|
if ix == -1 {
|
|
return nm
|
|
}
|
|
return nm[ix+1:]
|
|
}
|
|
|
|
// Namespace extracts the namespace portion of a Name (dropping the Name); this may be empty.
|
|
func (nm Name) Namespace() Name {
|
|
ix := strings.LastIndex(string(nm), NameDelimiter)
|
|
if ix == -1 {
|
|
return ""
|
|
}
|
|
return nm[:ix]
|
|
}
|