private object InvokeMethodSymbol(MethodSymbol method, List<Ast> args) { // create a new memory scope. this is where arguments will get defined // we wont overwrite any memory values since they will all be local here MemorySpaces.CreateScope(); var count = 0; if (method.MethodDeclr.Arguments.Count != args.Count) { throw new InvalidSyntax(String.Format("Wrong number of arguments passed to method {0}. Got {1}, expected {2}", method.MethodDeclr.MethodName.Token.TokenValue, args.Count, method.MethodDeclr.Arguments.Count)); } foreach (VarDeclrAst expectedArgument in method.MethodDeclr.Arguments) { var currentArgument = args[count]; var oldmemory = MemorySpaces.Current; // if the argument is coming from somewhere else, make sure to be able to // load the argument from its preferred space. if (currentArgument.CallingMemory != null) { MemorySpaces.Current = currentArgument.CallingMemory; } var value = GetValue(Exec(currentArgument)); // since we were just loading values from the argument space // switch back to the current space so we can assign the argument value // into our local working memory MemorySpaces.Current = oldmemory; if (expectedArgument.VariableValue == null) { MemorySpaces.Current.Define(expectedArgument.Token.TokenValue, value); } else { MemorySpaces.Current.Assign(expectedArgument.Token.TokenValue, value); } // if the passed in argument is a word and not a literal (like string or bool) then // pull its value from memory so we can match type to the target type var resolvedSymbol = (currentArgument.Token.TokenType == TokenType.Word ? MemorySpaces.Current.Get(currentArgument.Token.TokenValue) : args[count]) as Symbol; var resolvedType = resolvedSymbol != null ? resolvedSymbol.Type : currentArgument.AstSymbolType; if (currentArgument is MethodDeclr) { resolvedType = new BuiltInType(ExpressionTypes.Method); } if (!TokenUtil.EqualOrPromotable(expectedArgument.AstSymbolType, resolvedType)) { throw new InvalidSyntax(String.Format("Cannot pass argument {0} of type {1} to function {2} as argument {3} of type {4}", currentArgument.Token.TokenValue, currentArgument.AstSymbolType.TypeName, method.MethodDeclr.MethodName.Token.TokenValue, expectedArgument.VariableName.Token.TokenValue, expectedArgument.AstSymbolType.TypeName)); } count++; } var val = Exec(method.MethodDeclr.Body); MemorySpaces.PopScope(); return val; }
private void ValidateReturnStatementType(MethodDeclr ast, Symbol symbol) { if (!ResolvingTypes) { return; } IType returnStatementType; // no return found if (ast.ReturnAst == null) { returnStatementType = new BuiltInType(ExpressionTypes.Void); } else { returnStatementType = ast.ReturnAst.AstSymbolType; } var delcaredSymbol = ScopeUtil.CreateSymbolType(ast.MethodReturnType); // if its inferred, just use whatever the return statement i if (delcaredSymbol.ExpressionType == ExpressionTypes.Inferred) { return; } if (!TokenUtil.EqualOrPromotable(returnStatementType.ExpressionType, delcaredSymbol.ExpressionType)) { throw new InvalidSyntax(String.Format("Return type {0} for function {1} is not of the same type of declared method (type {2})", returnStatementType.ExpressionType, symbol.Name, delcaredSymbol.ExpressionType)); } }