better type checking for function args

This commit is contained in:
dfsek
2020-12-21 22:30:02 -07:00
parent 13fbb9bf54
commit cb7b3de48c
5 changed files with 36 additions and 18 deletions

View File

@@ -174,8 +174,8 @@ public class Parser {
@SuppressWarnings("unchecked")
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
if(binaryOperator.isStrictNumericOperator()) checkArithmeticOperation(left, right, binaryOperator.getType());
if(binaryOperator.isStrictBooleanOperator()) checkBooleanOperation(left, right, binaryOperator.getType());
if(binaryOperator.isStrictNumericOperator()) checkArithmeticOperation(left, right, binaryOperator);
if(binaryOperator.isStrictBooleanOperator()) checkBooleanOperation(left, right, binaryOperator);
switch(binaryOperator.getType()) {
case ADDITION_OPERATOR:
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
@@ -254,9 +254,17 @@ public class Parser {
if(fullStatement) checkType(tokens.get(0), Token.Type.STATEMENT_END);
FunctionBuilder<?> builder = functions.get(identifier.getContent());
if(args.size() != builder.getArguments() && builder.getArguments() != -1)
throw new ParseException("Expected " + builder.getArguments() + " arguments, found " + args.size() + ": " + identifier.getPosition());
return functions.get(identifier.getContent()).build(args, identifier.getPosition());
if(builder.argNumber() != -1 && args.size() != builder.argNumber())
throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size() + ": " + identifier.getPosition());
for(int i = 0; i < args.size(); i++) {
Returnable<?> argument = args.get(i);
if(builder.getArgument(i) == null)
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent() + ": " + identifier.getPosition());
checkReturnType(argument, builder.getArgument(i));
}
return builder.build(args, identifier.getPosition());
}
@@ -281,15 +289,15 @@ public class Parser {
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType() + ": " + returnable.getPosition());
}
private void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token.Type operation) throws ParseException {
private void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
throw new ParseException("Operation " + operation + " not supported between " + left.returnType() + " and " + right.returnType());
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType() + ": " + operation.getPosition());
}
}
private void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token.Type operation) throws ParseException {
private void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) {
throw new ParseException("Operation " + operation + " not supported between " + left.returnType() + " and " + right.returnType());
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType() + ": " + operation.getPosition());
}
}
}

View File

@@ -1,5 +0,0 @@
package com.dfsek.terra.api.structures.parser.lang;
public interface Argument<T> {
T parse(String input);
}

View File

@@ -9,5 +9,7 @@ import java.util.List;
public interface FunctionBuilder<T extends Function<?>> {
T build(List<Returnable<?>> argumentList, Position position) throws ParseException;
int getArguments();
int argNumber();
Returnable.ReturnType getArgument(int position);
}