mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-30 19:21:39 +00:00
add duplicate-check for user-defined subroutines, as in the C impl
This commit is contained in:
parent
b0685a759a
commit
8065237641
4 changed files with 41 additions and 7 deletions
|
|
@ -18,6 +18,8 @@ run_mlr --from $indir/2.dkvp put 'subr s() {return}'
|
|||
|
||||
mlr_expect_fail --from $indir/2.dkvp put 'call s()'
|
||||
|
||||
mlr_expect_fail -n put 'subr s(){} subr s(){}'
|
||||
|
||||
run_mlr --from $indir/2.dkvp put -v -q '
|
||||
func s(x) {
|
||||
return x*2;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ a=eks,b=pan,i=2,x=0.7586799647899636,y=0.5221511083334797
|
|||
|
||||
mlr --from ./reg-test/input/2.dkvp put call s()
|
||||
|
||||
mlr -n put subr s(){} subr s(){}
|
||||
|
||||
mlr --from ./reg-test/input/2.dkvp put -v -q
|
||||
func s(x) {
|
||||
return x*2;
|
||||
|
|
|
|||
|
|
@ -206,6 +206,11 @@ func (this *UDFManager) Install(udf *UDF) {
|
|||
this.functions[udf.signature.funcOrSubrName] = udf
|
||||
}
|
||||
|
||||
func (this *UDFManager) ExistsByName(name string) bool {
|
||||
_, ok := this.functions[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Example AST for UDF definition and callsite:
|
||||
|
||||
|
|
@ -251,6 +256,16 @@ func (this *RootNode) BuildAndInstallUDF(astNode *dsl.ASTNode) error {
|
|||
lib.InternalCodingErrorIf(len(astNode.Children) != 2 && len(astNode.Children) != 3)
|
||||
|
||||
functionName := string(astNode.Token.Lit)
|
||||
|
||||
if this.udsManager.ExistsByName(functionName) {
|
||||
return errors.New(
|
||||
fmt.Sprintf(
|
||||
"Miller: function named \"%s\" has already been defined.",
|
||||
functionName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
parameterListASTNode := astNode.Children[0]
|
||||
functionBodyASTNode := astNode.Children[1]
|
||||
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ func NewUDS(
|
|||
// For when a subroutine is called before being defined. This gives us something
|
||||
// to go back and fill in later once we've encountered the subroutine definition.
|
||||
func NewUnresolvedUDS(
|
||||
functionName string,
|
||||
subroutineName string,
|
||||
callsiteArity int,
|
||||
) *UDS {
|
||||
signature := NewSignature(functionName, callsiteArity, nil, nil)
|
||||
signature := NewSignature(subroutineName, callsiteArity, nil, nil)
|
||||
uds := NewUDS(signature, nil)
|
||||
return uds
|
||||
}
|
||||
|
|
@ -162,8 +162,8 @@ func NewUDSManager() *UDSManager {
|
|||
}
|
||||
}
|
||||
|
||||
func (this *UDSManager) LookUp(functionName string, callsiteArity int) (*UDS, error) {
|
||||
uds := this.subroutines[functionName]
|
||||
func (this *UDSManager) LookUp(subroutineName string, callsiteArity int) (*UDS, error) {
|
||||
uds := this.subroutines[subroutineName]
|
||||
if uds == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ func (this *UDSManager) LookUp(functionName string, callsiteArity int) (*UDS, er
|
|||
return nil, errors.New(
|
||||
fmt.Sprintf(
|
||||
"Miller: subroutine %s invoked with %d argument%s; expected %d",
|
||||
functionName,
|
||||
subroutineName,
|
||||
callsiteArity,
|
||||
lib.Plural(callsiteArity),
|
||||
uds.signature.arity,
|
||||
|
|
@ -185,6 +185,11 @@ func (this *UDSManager) Install(uds *UDS) {
|
|||
this.subroutines[uds.signature.funcOrSubrName] = uds
|
||||
}
|
||||
|
||||
func (this *UDSManager) ExistsByName(name string) bool {
|
||||
_, ok := this.subroutines[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Example AST for UDS definition and callsite:
|
||||
|
||||
|
|
@ -229,7 +234,17 @@ func (this *RootNode) BuildAndInstallUDS(astNode *dsl.ASTNode) error {
|
|||
lib.InternalCodingErrorIf(astNode.Children == nil)
|
||||
lib.InternalCodingErrorIf(len(astNode.Children) != 2 && len(astNode.Children) != 3)
|
||||
|
||||
functionName := string(astNode.Token.Lit)
|
||||
subroutineName := string(astNode.Token.Lit)
|
||||
|
||||
if this.udsManager.ExistsByName(subroutineName) {
|
||||
return errors.New(
|
||||
fmt.Sprintf(
|
||||
"Miller: subroutine named \"%s\" has already been defined.",
|
||||
subroutineName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
parameterListASTNode := astNode.Children[0]
|
||||
subroutineBodyASTNode := astNode.Children[1]
|
||||
|
||||
|
|
@ -263,7 +278,7 @@ func (this *RootNode) BuildAndInstallUDS(astNode *dsl.ASTNode) error {
|
|||
typeGatedParameterNames[i] = typeGatedParameterName
|
||||
}
|
||||
|
||||
signature := NewSignature(functionName, arity, typeGatedParameterNames, nil)
|
||||
signature := NewSignature(subroutineName, arity, typeGatedParameterNames, nil)
|
||||
|
||||
subroutineBody, err := this.BuildStatementBlockNode(subroutineBodyASTNode)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue