Skip to content

Commit

Permalink
Coerce arguments to functions, in some cases (#144)
Browse files Browse the repository at this point in the history
* Coerce arguments to functions, in some cases

This is a bit of a sneaky change, but it is useful to convert arguments
to lists in some cases:

* If a function is defined that accepts a single parameter.
* BUT multiple arguments are actually passed to that function
* THEN
  * If the parameter is not variadic
  * And the parameter is untyped, or typed as a list
  * REPLACE THE Arguments with a list containing their entries.

This means:

    (set! and (fn* (xs:list) ... )

Can then be called:

    (and true false true true ..)

Because the arguments will be rewritten as if they were called:

    (and (list true false true true ..)

This is general purpose, and applies to all functions.

I _think_ it's a good idea, but we'll see.

* Updated location of the buildvcs flag
  • Loading branch information
skx authored Mar 6, 2024
1 parent 1615bd8 commit 8360065
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
7 changes: 4 additions & 3 deletions .github/run-tests.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#!/bin/bash

# I don't even ..
go env -w GOFLAGS="-buildvcs=false"


# Install the tools we use to test our code-quality.
#
# Here we setup the tools to install only if the "CI" environmental variable
Expand Down Expand Up @@ -37,9 +41,6 @@ echo "Launching shadowed-variable check .."
go vet -vettool=$(which shadow) ./...
echo "Completed shadowed-variable check .."

# I don't even ..
go env -w GOFLAGS="-buildvcs=false"

# Run golang tests
go test ./...

Expand Down
51 changes: 51 additions & 0 deletions eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,57 @@ func (ev *Eval) eval(exp primitive.Primitive, e *env.Environment, expandMacro bo
}
}

// Sneaky type-conversion.
//
// What we're trying to do here is coerce arguments a little:
//
// - If a function is defined in lisp
// - That takes ONE argument
// - But more are provided
// - THEN
// - Convert those arguments into a list and pass as a single arg
// - UNLESS
// - The argument to the function is meant for variadic usage
// - OR
// - The argument is typed as not taking a list
//
if len(proc.Args) == 1 && len(args) > 1 {

// Get the argument name
// If this is typed it will have ":blah" suffix
// If this is variadic it will have "&" prefix
//
arg := proc.Args[0].ToString()

//
// Ignore variadic argument
//
if len(arg) > 0 && arg[0] != '&' {

//
// Is there a type-suffix? Split by ":" to find out
//
parts := strings.Split(arg, ":")

//
// If there is NOT a type-suffix, or there is one that specifies a list
//
if len(parts) == 0 || (len(parts) == 2 && parts[1] == "list") {

// Convert the argument supplied into a list
var tmp primitive.List
for _, x := range args {
tmp = append(tmp, x)
}

// And replace the arguments
args = []primitive.Primitive{
tmp,
}
}
}
}

//
// Check that the arguments supplied match those that are expected.
//
Expand Down

0 comments on commit 8360065

Please sign in to comment.