anchor.diff:      
       /// checks if the arguments' shapes are compatible with the result shape        
       let checkArgShapes (expr: ElemExprT<'T>) (argShapes: ShapeSpecT list) (resShape: ShapeSpecT) =
  +        // check number of arguments
           let nArgs = List.length argShapes
           let nReqArgs = requiredNumberOfArgs expr       
           if nReqArgs > nArgs then
               failwithf "the element expression requires at least %d arguments but only %d arguments were specified"
                   nReqArgs nArgs
   
  -        // TODO
  -        ()
  -
  -
  +        // check dimensionality of arguments
  +        let rec checkDims expr =
  +            match expr with
  +            | Leaf (ArgElement (Arg n, idx)) ->
  +                let idxDim = ShapeSpec.nDim idx
  +                let argDim = ShapeSpec.nDim argShapes.[n]
  +                if idxDim <> argDim then
  +                    failwithf 
  +                        "the argument with zero-based index %d has %d dimensions but was used  \
  +                         with %d dimensions in the element expression" n argDim idxDim
  +            | Leaf _ -> ()
  +
  +            | Unary (_, a) -> checkDims a
  +            | Binary (_, a, b) -> checkDims a; checkDims b
  +        checkDims expr
  +
  +    /// substitutes the specified size symbols with their replacements 
       let rec substSymSizes symSizes expr = 
           let sSub = substSymSizes symSizes
           let sSize = SymSizeEnv.subst symSizes
  
positive.code:             ArrayND.set idx ev res
          res
  
      let rec requiredNumberOfArgs expr =
          match expr with
          | Leaf (ArgElement (Arg n, _)) -> 
  
negative.code:             Unary (Sum (sumSym, first, last), expr) 
          | _ -> invalidArg "idx" "idx must be summation index obtained by calling sumIdx"
  
      /// If left=right, then thenExpr else elseExpr.
      let ifThenElse left right thenExpr elseExpr =
          Binary (IfThenElse (left, right), thenExpr, elseExpr)
  