public object Visit(Expr.Call expr) { object callee = Evaluate(expr.Callee); List <object> arguments = new List <object>(); foreach (Expr arg in expr.Arguments) { arguments.Add(Evaluate(arg)); } // Make sure we the callee is actually callable if (!(callee is ILoxCallable)) { throw new RuntimeErrorException(expr.Paren, "Can only call functions and classes."); } ILoxCallable function = (ILoxCallable)callee; // Make sure we are passing the correct number of arguments if (arguments.Count() != function.Arity) { throw new RuntimeErrorException(expr.Paren, $"Expected {function.Arity} argumuments, but got {arguments.Count()}."); } return(function.Call(this, arguments)); }
public void Validate_Call_expr_does_something_useful() { // Arrange var name = new Token(TokenType.IDENTIFIER, "to_string", null, 1); var identifier = new Expr.Identifier(name); var get = new Expr.Get(identifier, name); var paren = new Token(TokenType.RIGHT_PAREN, ")", null, 1); var callExpr = new Expr.Call(get, paren, new List <Expr>()); var bindings = new Dictionary <Expr, Binding> { { identifier, new NativeClassBinding(identifier, typeof(string)) } }; var typeValidationErrors = new List <TypeValidationError>(); var warnings = new List <CompilerWarning>(); // Act TypeValidator.Validate( new List <Stmt> { new Stmt.ExpressionStmt(callExpr) }, error => typeValidationErrors.Add(error), expr => bindings[expr], warning => warnings.Add(warning) ); // Assert Assert.Empty(typeValidationErrors); Assert.Empty(warnings); }
void superCall(Expr.Call sCallExpr) { Expr.Super superExpr = (Expr.Super)sCallExpr.callee; captureToken(superExpr.keyword); if (currentClass == null) { error("Cannot use 'super' outside of a class."); } else if (!currentClass.hasSuperclass) { error("Cannot use 'super' in a class with no superclass."); } captureToken(superExpr.method); byte name = identifierConstant(superExpr.method); getNamedVariable(syntheticToken("this")); byte argCount = compile_argumentList(sCallExpr.arguments); getNamedVariable(superExpr.keyword); emitBytes((byte)OpCode.OP_SUPER_INVOKE, name); emitByte(argCount); }
public object VisitCallExpr(Expr.Call expr) { object callee = Evaluate(expr.Callee); List <object> arguments = new List <object>(); foreach (Expr argument in expr.Arguments) { arguments.Add(Evaluate(argument)); } if (!(callee is LoxCallable)) { throw new RuntimeException( expr.Paren, "Can only call functions and classes."); } LoxCallable function = (LoxCallable)callee; int arity = function.Arity(); if (arguments.Count != arity) { throw new RuntimeException(expr.Paren, $"Expected {arity} arguments but got {arguments.Count}."); } return(function.Call(this, arguments)); }
public object VisitCallExpr(Expr.Call expr) { object callee = Evaluate(expr.Callee); IList <object> arguments = new List <object>(); foreach (var argument in expr.Arguments) { arguments.Add(Evaluate(argument)); } if (!(callee is ICallable)) { throw new RuntimeError(expr.Paren, "Can only call functions and classes"); } ICallable function = (ICallable)callee; if (arguments.Count != function.Arity()) { throw new RuntimeError(expr.Paren, "Expected " + function.Arity() + " arguments but got " + arguments.Count); } return(function.Call(this, arguments)); }
public object visitCallExpr(Expr.Call expr) { object callee = evaluate(expr.callee); List <object> arguments = new List <object>(); foreach (Expr argument in expr.arguments) { arguments.Add(evaluate(argument)); } if (!(callee is LoxCallable)) { throw new RuntimeError(expr.paren, "Can only call functions and classes."); } LoxCallable function = (LoxCallable)callee; if (arguments.Count != function.arity()) { throw new RuntimeError(expr.paren, "Expected " + function.arity() + " arguments but got " + arguments.Count + "."); } return(function.call(this, arguments)); }
public Unit VisitCallExpr(Expr.Call expr) { foreach (Expr argument in expr.Arguments) { Resolve(argument); } return(new Unit()); }
public object VisitCallExpr(Expr.Call expr) { Resolve(expr.Callee); foreach (var argument in expr.Arguments) { Resolve(argument); } return(null); }
public LoxVoid VisitCallExpr(Expr.Call expr) { Resolve(expr.Callee); foreach (Expr argument in expr.Arguments) { Resolve(argument); } return(null); }
public object visitCallExpr(Expr.Call expr) { resolve(expr.callee); foreach (Expr argument in expr.arguments) { resolve(argument); } return(null); }
/// <summary> /// Resolve a call expression /// </summary> /// <param name="expr">The expression</param> /// <returns></returns> public object Visit(Expr.Call expr) { Resolve(expr.Callee); foreach (Expr arg in expr.Arguments) { Resolve(arg); } return(null); }
void getCall(Expr.Call gCallExpr) { Expr.Get getExpr = (Expr.Get)gCallExpr.callee; compile(getExpr.object_); captureToken(getExpr.name); byte name = identifierConstant(getExpr.name); byte argCount = compile_argumentList(gCallExpr.arguments); emitBytes((byte)OpCode.OP_INVOKE, name); emitByte(argCount); }
public Value Visit(Expr.Call expr) { var function = this.GetFunction(expr.Callee); var args = new Value[Math.Max(expr.Arguments.Length, 0)]; for (var i = 0; i < args.Length; i++) { args[i] = expr.Arguments[i].Accept(this); } return(this._instructionBuilder.Call(function, args).RegisterName("calltmp")); }
public override VoidObject VisitCallExpr(Expr.Call expr) { if (expr.Callee is Expr.Get get) { VisitCallExprForGetCallee(expr, get); } else { VisitCallExprForOtherCallee(expr); } return(VoidObject.Void); }
private Expression EmitCallExpression(Expr.Call call) { if (call.FuncName.Ref.Symbol.FirstDeclarationOrDefault is FilterFunDeclaration filterDeclaration) { var args = new[] { EmitExpression(call.Arg0) }.Concat(call.Args.Select(expr => EmitExpression(expr))).ToArray(); if (args.Length > 0) { return(Expression.Call(filterDeclaration.Method, args)); } return(Expression.Call(filterDeclaration.Method)); } return(Expression.Empty()); }
public VoidObject VisitCallExpr(Expr.Call expr) { Resolve(expr.Callee); foreach (Expr argument in expr.Arguments) { Resolve(argument); } if (expr.Callee is Expr.Identifier identifierExpr) { ResolveLocalOrGlobal(expr, identifierExpr.Name); } return(VoidObject.Void); }
public object VisitCallExpr(Expr.Call expr) { object callee = Evalutate(expr.Callee); List <object> arguments = expr.Arguments .Select(e => Evalutate(e)) .ToList(); if (callee is ILoxCallable function) { if (arguments.Count != function.Arity) { throw new RuntimeError(expr.Paren, $"Expected {function.Arity} " + $"arguments but got {arguments.Count}."); } return(function.Call(this, arguments)); } throw new RuntimeError(expr.Paren, "Can only call functions and classes."); }
/* * Expr.Get and Expr.Super callees are intercepted * for separate treatment for invoke and property */ public object visitCallExpr(Expr.Call callExpr) { captureToken(callExpr.paren); byte argCount; if (callExpr.callee is Expr.Variable) // "common"/global functions { getNamedVariable(((Expr.Variable)callExpr.callee).name); argCount = compile_argumentList(callExpr.arguments); emitBytes((byte)OpCode.OP_CALL, argCount); return(null); } if (callExpr.callee is Expr.Get) // methods { getCall(callExpr); return(null); } if (callExpr.callee is Expr.Super) // super methods { superCall(callExpr); return(null); } if (callExpr.callee is Expr.Call) // nested calls { argCount = compile_argumentList(callExpr.arguments); visitCallExpr((Expr.Call)callExpr.callee); emitBytes((byte)OpCode.OP_CALL, argCount); return(null); } error("Can only call functions and classes."); // runtime error in clox return(null); }
public object VisitCallExpr(Expr.Call expr) { var callee = Evaluate(expr.callee); var args = new List <object>(); foreach (var arg in expr.arguments) { args.Add(Evaluate(arg)); } if (callee is ICallable function) { if (args.Count != function.Arity()) { throw new RuntimeException(expr.paren, $"Expected {function.Arity()} arguments but got {args.Count}."); } return(function.Call(this, args)); } throw new RuntimeException(expr.paren, "Can only call functions and classes"); }
private string VisitCallExpr(Expr.Call expr) { throw new NotImplementedException(); }
private void VisitCallExprForGetCallee(Expr.Call call, Expr.Get get) { string methodName = get.Name.Lexeme; if (get.Methods.Length == 0) { if (!get.Object.TypeReference.IsResolved) { // This is a bit of an oddball, but... We get here when an attempt is made to call a method on some // undefined type. (`Foo.do_stuff`) // // Now, this is a compile-time error, but the problem is that it's handled by this class itself; // encountering this error will not abort the tree traversal so we must avoid breaking it. } else { // This is even more odd, but we must ensure that we have well-defined semantics in the weird case // where this would happen. TypeValidationErrorCallback(new TypeValidationError( call.Paren, $"Internal compiler error: no methods with name '{methodName}' could be found. This is a critical " + $"error that should have aborted the compilation before the {nameof(TypesResolvedValidator)} " + "validation is started. " )); } } else if (get.Methods.Length == 1) { MethodInfo method = get.Methods.Single(); var parameters = method.GetParameters(); // There is exactly one potential method to call in this case. We use this fact to provide better // error messages to the caller than when calling an overloaded method. if (parameters.Length != call.Arguments.Count) { TypeValidationErrorCallback(new TypeValidationError( call.Paren, $"Method '{methodName}' has {parameters.Length} parameter(s) but was called with {call.Arguments.Count} argument(s)" )); return; } for (int i = 0; i < call.Arguments.Count; i++) { ParameterInfo parameter = parameters[i]; Expr argument = call.Arguments[i]; if (!argument.TypeReference.IsResolved) { throw new PerlangInterpreterException( $"Internal compiler error: Argument '{argument}' to function {methodName} not resolved"); } // FIXME: call.Token is a bit off here; it would be useful when constructing compiler warnings based // on this if we could provide the token for the argument expression instead. However, the Expr type // as used by 'argument' is a non-token-based expression so this is currently impossible. // FIXME: `null` here has disadvantages as described elsewhere. if (!TypeCoercer.CanBeCoercedInto(parameter.ParameterType, argument.TypeReference.ClrType, null)) { // Very likely refers to a native method, where parameter names are not available at this point. TypeValidationErrorCallback(new TypeValidationError( argument.TypeReference.TypeSpecifier !, $"Cannot pass {argument.TypeReference.ClrType.ToTypeKeyword()} argument as {parameter.ParameterType.ToTypeKeyword()} parameter to {methodName}()")); } } } else { // Method is overloaded. Try to resolve the best match we can find. foreach (MethodInfo method in get.Methods) { var parameters = method.GetParameters(); if (parameters.Length != call.Arguments.Count) { // The number of parameters do not match, so this method will never be a suitable candidate // for our expression. continue; } bool coercionsFailed = false; for (int i = 0; i < call.Arguments.Count; i++) { ParameterInfo parameter = parameters[i]; Expr argument = call.Arguments[i]; if (!argument.TypeReference.IsResolved) { throw new PerlangInterpreterException( $"Internal compiler error: Argument '{argument}' to method {methodName} not resolved"); } // FIXME: The same caveat as above with call.Token applies here as well. if (!TypeCoercer.CanBeCoercedInto(parameter.ParameterType, argument.TypeReference.ClrType, null)) { coercionsFailed = true; break; } } if (!coercionsFailed) { // We have found a suitable overload to use. Update the expression get.Methods = ImmutableArray.Create(method); return; } } TypeValidationErrorCallback(new NameResolutionTypeValidationError( call.Paren, $"Method '{call.CalleeToString}' found, but no overload matches the provided parameters." )); } }
string Expr.ILoxVisitor <string> .VisitCallExpr(Expr.Call expr) { throw new NotImplementedException(); }
public object VisitCallExpr(Expr.Call expr, object options) { return(Parenthesize2("call", expr.callee, Parenthesize("args: ", expr.arguments.ToArray()))); }
public string visitCallExpr(Expr.Call expr) { throw new NotImplementedException(); }
public string VisitCallExpr(Expr.Call expr) { throw new System.NotImplementedException(); }
public string VisitCallExpr(Expr.Call expr) { return(Parenthesize("func", expr)); }
public string VisitCallExpr(Expr.Call expr) { string arguments = string.Join(", ", expr.Arguments.Select(e => PrintExpr(e))); return($"{PrintExpr(expr.Callee)}({arguments})"); }
public Token visitCallExpr(Expr.Call call) { return(evaluate(call.callee)); }
private void VisitCallExprForOtherCallee(Expr.Call expr) { Binding binding = GetVariableOrFunctionCallback(expr); if (binding == null) { TypeValidationErrorCallback( new NameResolutionTypeValidationError(expr.Paren, $"Attempting to call undefined function '{expr.CalleeToString}'") ); return; } IList <Parameter> parameters; string functionName; switch (binding) { case FunctionBinding functionBinding: Stmt.Function function = functionBinding.Function; if (function == null) { throw new NameResolutionTypeValidationError(expr.Paren, $"Internal compiler error: function for {expr} not expected to be null"); } parameters = function.Parameters; functionName = function.Name.Lexeme; break; default: throw new NameResolutionTypeValidationError(expr.Paren, $"Attempting to call invalid function {binding} using {expr}"); } if (parameters.Count != expr.Arguments.Count) { TypeValidationErrorCallback(new TypeValidationError( expr.Paren, $"Function '{functionName}' has {parameters.Count} parameter(s) but was called with {expr.Arguments.Count} argument(s)") ); return; } for (int i = 0; i < expr.Arguments.Count; i++) { Parameter parameter = parameters[i]; Expr argument = expr.Arguments[i]; if (!argument.TypeReference.IsResolved) { throw new PerlangInterpreterException($"Internal compiler error: Argument '{argument}' to function {functionName} not resolved"); } if (argument.TypeReference.IsNullObject) { compilerWarningCallback(new CompilerWarning($"Null parameter detected for '{parameter.Name.Lexeme}'", expr.TokenAwareCallee.Token, WarningType.NULL_USAGE)); } // FIXME: expr.Token is an approximation here as well (see other similar comments in this file) // FIXME: `null` here means that small-constants of e.g. `long` will not be able to be passed as `int` parameters. if (!TypeCoercer.CanBeCoercedInto(parameter.TypeReference, argument.TypeReference, null)) { if (parameter.Name != null) { TypeValidationErrorCallback(new TypeValidationError( argument.TypeReference.TypeSpecifier !, $"Cannot pass {argument.TypeReference.ClrType.ToTypeKeyword()} argument as parameter '{parameter.Name.Lexeme}: {parameter.TypeReference.ClrType.ToTypeKeyword()}' to {functionName}()")); } else { // Very likely refers to a native method, where parameter names are not available at this point. TypeValidationErrorCallback(new TypeValidationError( argument.TypeReference.TypeSpecifier !, $"Cannot pass {argument.TypeReference.ClrType.ToTypeKeyword()} argument as {parameter.TypeReference.ClrType.ToTypeKeyword()} parameter to {functionName}()")); } } } }
public object VisitCallExpr(Expr.Call expr, object options = null) { return(null); }