Skip to content

Commit

Permalink
length() function
Browse files Browse the repository at this point in the history
  • Loading branch information
cardillan committed Nov 3, 2024
1 parent 8d27de8 commit 1b1d343
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ public LogicValue visitFunctionArgument(FunctionArgument node) {
public LogicValue visitFunctionCall(FunctionCall call) {
// Solve special cases
return switch (call.getFunctionName()) {
case "length" -> handleLength(call);
case "min", "max" -> handleMinMax(call);
case "mlog" -> handleMlog(call, false);
case "mlogSafe" -> handleMlog(call, true);
Expand Down Expand Up @@ -1821,16 +1822,31 @@ boolean requiresParameter() {

private static final Pattern PLACEHOLDER_MATCHER = Pattern.compile("\\{\\d}");

private LogicValue handleMinMax(FunctionCall call) {
if (call.getArguments().size() < 2) {
error(call, "Not enough arguments to the '%s' function (expected 2 or more, found %d).",
call.getFunctionName(), call.getArguments().size());
private LogicValue handleLength(FunctionCall call) {
if (call.getArguments().size() != 1) {
error(call, "Function '%s': wrong number of arguments (expected %d, found %d).",
call.getFunctionName(), 1, call.getArguments().size());
}
validateStandardFunctionArguments(call.getArguments());

setSubcontextType(AstSubcontextType.ARGUMENTS, 1.0);
final List<LogicFunctionArgument> arguments = processArguments(call.getArguments());

clearSubcontextType();
return LogicNumber.get(arguments.size());
}

private LogicValue handleMinMax(FunctionCall call) {
validateStandardFunctionArguments(call.getArguments());

setSubcontextType(AstSubcontextType.ARGUMENTS, 1.0);
final List<LogicFunctionArgument> arguments = processArguments(call.getArguments());

if (arguments.size() < 2) {
error(call, "Not enough arguments to the '%s' function (expected 2 or more, found %d).",
call.getFunctionName(), call.getArguments().size());
}

setSubcontextType(AstSubcontextType.SYSTEM_CALL, 1.0);
LogicValue result;
if (arguments.size() >= 2) {
Expand Down Expand Up @@ -1987,7 +2003,7 @@ private LogicValue handleFormattedOutput(FunctionCall call, Formatter formatter)
} else {
// Only create instruction for each argument
arguments.forEach(argument -> emit(formatter.createInstruction(this, argument.value())));
returnValue = arguments.get(arguments.size() - 1).value();
returnValue = arguments.isEmpty() ? NULL : arguments.get(arguments.size() - 1).value();
}

if (formatter.createsNewLine()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,4 +408,69 @@ void foo()
createInstruction(END)
);
}

@Test
void compilesVarargFunction() {
assertCompilesTo("""
inline void foo(args...)
print(args);
end;
foo(1, 2, 3);
foo();
""",
createInstruction(LABEL, var(1000)),
createInstruction(PRINT, "1"),
createInstruction(PRINT, "2"),
createInstruction(PRINT, "3"),
createInstruction(LABEL, var(1001)),
createInstruction(LABEL, var(1002)),
createInstruction(LABEL, var(1003)),
createInstruction(END)
);
}

@Test
void compilesVarargFunctionCall() {
assertCompilesTo("""
inline void foo(args...)
print(args);
end;
inline void bar(args...)
foo(args, args);
end;
bar(1, 2, 3);
""",
createInstruction(LABEL, var(1000)),
createInstruction(LABEL, var(1002)),
createInstruction(PRINT, "1"),
createInstruction(PRINT, "2"),
createInstruction(PRINT, "3"),
createInstruction(PRINT, "1"),
createInstruction(PRINT, "2"),
createInstruction(PRINT, "3"),
createInstruction(LABEL, var(1003)),
createInstruction(LABEL, var(1001)),
createInstruction(END)
);
}

@Test
void compilesLengthFunction() {
assertCompilesTo("""
inline void foo(args...)
print(length(args));
end;
inline void bar(args...)
foo(args, args);
end;
bar(1, 2, 3);
""",
createInstruction(LABEL, var(1000)),
createInstruction(LABEL, var(1002)),
createInstruction(PRINT, "6"),
createInstruction(LABEL, var(1003)),
createInstruction(LABEL, var(1001)),
createInstruction(END)
);
}
}
33 changes: 32 additions & 1 deletion doc/syntax/SYNTAX-4-FUNCTIONS.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,22 @@ end;
foo(1, 2, 3);
```

The vararg parameter may be passed to a standard function as well. For example
### Varargs as function arguments

The vararg parameter may be passed to standard functions as well. For example

```
inline void foo(args...)
println(min(args));
println(max(args));
println($"Values: $, $, $, $", args);
end;
foo(1, 2, 3, 4);
foo(1, 2, 3, 4, 5); // Causes error in the call to println() function, as it expectsexactly 4 arguments
```

An `out` argument may also be passed via vararg to a function that accepts it:

```
inline void foo(arg...)
Expand Down Expand Up @@ -541,6 +556,22 @@ end;
foo(1, 2, 3);
```

### The `length()` function

A `length()` function determines the number of arguments passed into the vararg parameter. `0` is returned when no argument was passed to the vararg parameter.

```
inline void foo(args...)
println(length(args));
end;
foo(); // 0
foo(10); // 1
foo(1, 2, 3, 4, 5); // 5
```

The function always takes just one argument. When the argument passed in is not a vararg, the function returns `1`.

## Function overloading

Mindcode supports function overloading. Several functions can have the same name, provided they differ in the number of arguments they take. For example:
Expand Down

0 comments on commit 1b1d343

Please sign in to comment.