Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow named arguments anywhere #491

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/Type/Infer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2037,14 +2037,11 @@ isAnnot _ = False

splitNamedArgs :: Ranged e => [(Maybe (Name,Range),e)] -> Inf ([e],[((Name,Range),e)])
splitNamedArgs nargs
= do let (nfixed,rest) = span (isNothing . fst) nargs
(nnamed,morefixed) = span (not . isNothing . fst) rest
= do let nfixed = filter (isNothing . fst) nargs
nnamed = filter (not . isNothing . fst) nargs
fixed = map snd nfixed
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using span, we just filter by whether they have a name.

named = [((name,rng),expr) | (Just (name,rng),expr) <- nnamed]
-- check that named arguments all come after the positional ones
case morefixed of
[] -> return ()
(arg:_) -> infError (getRange (snd arg)) (text "positional arguments cannot follow named arguments")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No error is needed any more!

checkDuplicates [] named

return (seqqList fixed,seqqList named)
Expand Down
6 changes: 3 additions & 3 deletions src/Type/InferMonad.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1461,9 +1461,9 @@ filterMatchNameContextEx range ctx candidates
matchArgs :: Bool -> [Type] -> [(Name,Type)] -> Maybe Type -> (Name,NameInfo) -> Inf [(Name,NameInfo,Rho)]
matchArgs matchSome fixed named mbResTp (name,info)
= do free <- freeInGamma
-- traceDefDoc $ \penv -> text " match fixed:" <+> list [Pretty.ppType penv fix | fix <- fixed]
-- <+> text ", named" <+> list [Pretty.ppParam penv nametp | nametp <- named]
-- <+> text "on" <+> Pretty.ppParam penv (name,infoType info)
-- traceDefDoc $ \penv -> text " match fixed:" <+> list [Pretty.ppType penv fix | fix <- fixed]
-- <+> text ", named" <+> list [Pretty.ppParam penv nametp | nametp <- named]
-- <+> text "on" <+> Pretty.ppParam penv (name,infoType info)
res <- runUnify (matchArguments matchSome range free (infoType info) fixed named mbResTp)
case res of
(Right rho,_) -> return [(name,info,rho)]
Expand Down
6 changes: 3 additions & 3 deletions src/Type/Unify.hs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ matchArguments matchSome range free tp fixed named mbExpResTp
then unifyError NoMatch
else do -- trace (" matchArguments: " ++ show (map pretty pars, map pretty fixed, map pretty named)) $ return ()
-- subsume fixed parameters
let (fpars,npars) = splitAt (length fixed) pars
let parsNotNamedArg = filter (\(nm,tp) -> nm `notElem` map fst named) pars
let (fpars,rest) = splitAt (length fixed) parsNotNamedArg
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only other change really is during unification removing all the supplied named arguments from parameters before determining which ones are fixed.

Copy link
Collaborator Author

@TimWhiting TimWhiting May 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than two more one line changes just below this, all of the rest of the changes are in updating tests.

mapM_ (\(tpar,targ) -> subsumeSubst range free (unOptional tpar) targ) (zip (map snd fpars) fixed)
-- subsume named parameters
mapM_ (\(name,targ) -> case lookup name npars of
mapM_ (\(name,targ) -> case lookup name pars of
Nothing -> unifyError NoMatch
Just tpar -> subsumeSubst range free (unOptional tpar) targ
) named
Expand All @@ -151,7 +152,6 @@ matchArguments matchSome range free tp fixed named mbExpResTp
Just expTp -> do subsumeSubst range free expTp resTp
return ()
-- check the rest is optional or implicit
let rest = [(nm,tpar) | (nm,tpar) <- npars, not (nm `elem` map fst named)]
if (matchSome || all isOptionalOrImplicit rest)
then do subst rho1
else unifyError NoMatch
Expand Down
1 change: 0 additions & 1 deletion test/syntax/config.json

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions test/syntax/no-run/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"flags": "-l"
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions test/syntax/no-run/wrong/braces1.kk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test/syntax/no-run/wrong/braces1@kk(4,15): parse error: invalid syntax
unexpected ")"
expecting ":", guard condition "|", "->" or "{"
File renamed without changes.
3 changes: 3 additions & 0 deletions test/syntax/no-run/wrong/braces2.kk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test/syntax/no-run/wrong/braces2@kk(4,15): parse error: invalid syntax
unexpected "->"
expecting "," or ")"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
test/syntax/wrong/unused1@kk(2, 5): parse error: invalid syntax
test/syntax/no-run/wrong/unused1@kk(2, 5): parse error: invalid syntax
unexpected 2
expecting "@", "(", "[", "{", "fn", operator, ":=", ";", "return" or "}"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
test/syntax/wrong/unused2@kk(2, 9): parse error: invalid syntax
test/syntax/no-run/wrong/unused2@kk(2, 9): parse error: invalid syntax
unexpected identifier "print"
expecting "@", "(", "[", "{", "fn", operator, ":=", ";", "return" or "}"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
test/syntax/wrong/unused3@kk(3, 5): parse error: invalid syntax
test/syntax/no-run/wrong/unused3@kk(3, 5): parse error: invalid syntax
unexpected identifier "xs"
expecting "@", "(", "[", "{", "fn", operator, ":=", ";", "return" or "}"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
test/syntax/wrong/utf1@kk(4,13): type error: types do not match
test/syntax/no-run/wrong/utf1@kk(4,13): type error: types do not match
context : 2 + "hello effectful world!"
term : "hello effectful world!"
inferred type: string
Expand Down
32 changes: 32 additions & 0 deletions test/syntax/run/named-anywhere.kk
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Parameters are "required" or "optional" (implicits are required, yet effectively optional until resolved)
// Arguments are "fixed" or "named"

// After matching the named arguments to formal parameters, the fixed arguments must match the ordering of the remaining parameters, with optional arguments staying optional.

// TODO: Change compiler terminology to "required" and "optional" for parameters instead of "fixed" and "named".
// All formal parameters are named after all (except for higher order functions, which typically use only required arguments - can they use even use optional?).

fun f(required: int, trailingrequired: () -> int, optional: int = 1, ?an-implicit: int): console ()
println(required.show ++ " + " ++ trailingrequired().show ++ " + " ++ optional.show ++ " + " ++ ?an-implicit.show)
val result = required + optional + ?an-implicit + trailingrequired()
println(result)

fun f2(required: int, fx: (int, ?c:int) -> int): int
val c = 1
fx(required) + fx(?c=2, required)

val basic/an-implicit = 3

fun main()
// Normal ordering, using default values for optional parameters
f(1, {0})
// Pass an optional parameter as a fixed argument
f(1, {2}, 3)
// Defer trailing lambda till after named arguments (this is the main use case for this feature)
f(1, optional=2) fn() 1
// Named argument first, including implicits
f(?an-implicit=10, optional=0, 1, {2})
// Use name for required argument to intentionally change order
f(optional=0, ?an-implicit=30, trailingrequired={2}, 1)
f(trailingrequired=fn() 1, -1)

12 changes: 12 additions & 0 deletions test/syntax/run/named-anywhere.kk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
1 + 0 + 1 + 3
5
1 + 2 + 3 + 3
9
1 + 1 + 2 + 3
7
1 + 2 + 0 + 10
13
1 + 2 + 0 + 30
33
-1 + 1 + 1 + 3
4
9 changes: 9 additions & 0 deletions test/syntax/run/pattern-match-in-param.kk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
f(2, [1], Just([2, 3])) -> 6
f(1, [1], Just([1])) -> syntax/run/pattern-match-in-param(1,34): f: pattern match failure
g(1, 2) -> 1
h([2,3]) -> 2
h() -> 1
i(0) -> 1
j(0) -> 1
k([]) -> syntax/run/pattern-match-in-param(23,12): k: pattern match failure
l((1, 2, 3)) -> 1
Empty file.
6 changes: 6 additions & 0 deletions test/syntax/run/tail.kk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/@virtual/syntax/run/tail/@main@kk(1,28): type error: identifier println cannot be resolved@
context : println
inferred type: _
candidates : println: (s : string) -> console ()
show/println : forall<a> (x : a, ?show : (a) -> string) -> console ()
hint : give a type annotation or qualify the name?
1 change: 1 addition & 0 deletions test/syntax/run/tail2.kk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Done
3 changes: 0 additions & 3 deletions test/syntax/wrong/braces1.kk.out

This file was deleted.

3 changes: 0 additions & 3 deletions test/syntax/wrong/braces2.kk.out

This file was deleted.