anchor.diff:      let private checkType (args: Fabel.Expr list) successContinuation =
           match args.Head.Type with
           | Fabel.UnknownType ->
  -            successContinuation () |> Solved
  +            successContinuation () |> Some
           | Fabel.PrimitiveType kind ->
               match kind with
               | Fabel.Number _ | Fabel.String _ | Fabel.Boolean | Fabel.Unit ->
  -                successContinuation () |> Solved
  +                successContinuation () |> Some
               | Fabel.Function _ | Fabel.Array _ | Fabel.Regex _ ->
                   failwithf "Unexpected operands: %A" args
           | Fabel.DeclaredType typ ->
  -            Partial (typ.FullName, failwith "TODO: Method name for non-primitive operators", args)
  -
  -    let unaryOp range typ op arg =
  -        checkType [arg] (fun () ->
  +            failwith "TODO: Custom operators"
  +
  +    let unaryOp range typ args op =
  +        checkType args (fun () ->
               let op = Fabel.UnaryOp op |> Fabel.Value
  -            Fabel.Apply(op, [arg], false, typ, range))
  -
  -    let binaryOp range typ op left right =
  -        checkType [left; right] (fun () ->
  +            Fabel.Apply(op, args, false, typ, range))
  +
  +    let binaryOp range typ args op =
  +        checkType args (fun () ->
               let op = Fabel.BinaryOp op |> Fabel.Value
  -            Fabel.Apply(op, [left; right], false, typ, range))
  -
  -    let logicalOp range typ op left right =
  -        checkType [left; right] (fun () ->
  +            Fabel.Apply(op, args, false, typ, range))
  +
  +    let logicalOp range typ args op =
  +        checkType args (fun () ->
               let op = Fabel.LogicalOp op |> Fabel.Value
  -            Fabel.Apply(op, [left; right], false, typ, range))
  +            Fabel.Apply(op, args, false, typ, range))
   
       // TODO: Check primitive args also here?
  -    let math range typ methName args =
  -        jsCoreLibCall range typ "Math" methName args |> Solved
  +    let math range typ args methName =
  +        jsCoreLibCall range typ "Math" methName args |> Some
   
       let operators com (info: Fabel.ApplyInfo) =
  -        let range, typ = info.range, info.returnType
  -        match info.methodName, (info.callee, info.args) with
  +        let r, typ, args = info.range, info.returnType, info.args
  +        match info.methodName with
           // F# Compiler actually converts all logical operations to IfThenElse expressions
  -        | "&&", TwoArgs (x, y) -> logicalOp range typ LogicalAnd x y
  -        | "||", TwoArgs (x, y) -> logicalOp range typ LogicalOr x y
  +        | "&&" -> logicalOp r typ args LogicalAnd
  +        | "||" -> logicalOp r typ args LogicalOr
           // TODO: If we're comparing against null, we should use non-strict equality
  -        | "<>", TwoArgs (x, y) -> binaryOp range typ BinaryUnequalStrict x y
  -        | "=", TwoArgs (x, y) -> binaryOp range typ BinaryEqualStrict x y
  -        | "+", TwoArgs (x, y) -> binaryOp range typ BinaryPlus x y
  -        | "-", TwoArgs (x, y) -> binaryOp range typ BinaryMinus x y
  -        | "*", TwoArgs (x, y) -> binaryOp range typ BinaryMultiply x y
  -        | "/", TwoArgs (x, y) -> binaryOp range typ BinaryDivide x y
  -        | "%", TwoArgs (x, y) -> binaryOp range typ BinaryModulus x y
  -        | "<<<", TwoArgs (x, y) -> binaryOp range typ BinaryShiftLeft x y
  -        | ">>>", TwoArgs (x, y) -> binaryOp range typ BinaryShiftRightSignPropagating x y
  -        | "&&&", TwoArgs (x, y) -> binaryOp range typ BinaryAndBitwise x y
  -        | "|||", TwoArgs (x, y) -> binaryOp range typ BinaryOrBitwise x y
  -        | "^^^", TwoArgs (x, y) -> binaryOp range typ BinaryXorBitwise x y
  -        | "~~~", OneArg x -> unaryOp range typ UnaryNotBitwise x
  -        | "not", OneArg x -> unaryOp range typ UnaryNot x
  -        | "abs", _ -> math range typ "abs" info.args
  -        | "acos", _ -> math range typ "acos" info.args
  -        | "asin", _ -> math range typ "asin" info.args
  -        | "atan", _ -> math range typ "atan" info.args
  -        | "atan2", _ -> math range typ "atan2" info.args
  -        | "ceil", _ -> math range typ "ceil" info.args
  -        | "cos", _ -> math range typ "cos" info.args
  -        | "exp", _ -> math range typ "exp" info.args
  -        | "floor", _ -> math range typ "floor" info.args
  -        | "log", _ -> math range typ "log" info.args
  -        | "log10", _ -> math range typ "LN10" info.args
  +        | "<>" -> binaryOp r typ args BinaryUnequalStrict
  +        | "=" -> binaryOp r typ args BinaryEqualStrict
  +        | "+" -> binaryOp r typ args BinaryPlus
  +        | "-" -> binaryOp r typ args BinaryMinus
  +        | "*" -> binaryOp r typ args BinaryMultiply
  +        | "/" -> binaryOp r typ args BinaryDivide
  +        | "%" -> binaryOp r typ args BinaryModulus
  +        | "<<<" -> binaryOp r typ args BinaryShiftLeft
  +        | ">>>" -> binaryOp r typ args BinaryShiftRightSignPropagating
  +        | "&&&" -> binaryOp r typ args BinaryAndBitwise
  +        | "|||" -> binaryOp r typ args BinaryOrBitwise
  +        | "^^^" -> binaryOp r typ args BinaryXorBitwise
  +        | "~~~" -> unaryOp r typ args UnaryNotBitwise
  +        | "not" -> unaryOp r typ args UnaryNot
  +        | "abs" -> math r typ args "abs"
  +        | "acos" -> math r typ args "acos"
  +        | "asin" -> math r typ args "asin"
  +        | "atan" -> math r typ args "atan"
  +        | "atan2" -> math r typ args "atan2"
  +        | "ceil" -> math r typ args "ceil"
  +        | "cos" -> math r typ args "cos"
  +        | "exp" -> math r typ args "exp"
  +        | "floor" -> math r typ args "floor"
  +        | "log" -> math r typ args "log"
  +        | "log10" -> math r typ args "LN10"
           // TODO: optimize square pow: x * x
  -        | "pown", _ | "**", _ -> math range typ "pow" info.args
  -        | "round", _ -> math range typ "round" info.args
  -        | "sin", _ -> math range typ "sin" info.args
  -        | "sqrt", _ -> math range typ "sqrt" info.args
  -        | "tan", _ -> math range typ "tan" info.args
  -        | _ -> Untouched
  -
  -    let intrinsicFunctions com (info: Fabel.ApplyInfo) =
  -        match info.methodName, (info.callee, info.args) with
  -        | "GetArray", TwoArgs (ar, idx) -> Fabel.Get (ar, idx, info.returnType) |> Solved
  -        | "SetArray", ThreeArgs (ar, idx, value) -> Fabel.Set (ar, Some idx, value, info.range) |> Solved
  -        | _ -> Untouched
  -
  -    let fsharpMap com (info: Fabel.ApplyInfo) =
  -        match info.methodName with
  -        | "add" | "Add" -> Instance "set"
  -        | "containsKey" | "ContainsKey" -> Instance "has"
  -        | "Count" -> Getter "size"
  -        | "isEmpty" | "IsEmpty" ->
  +        | "pown" | "**" -> math r typ args "pow"
  +        | "round" -> math r typ args "round"
  +        | "sin" -> math r typ args "sin"
  +        | "sqrt" -> math r typ args "sqrt"
  +        | "tan" -> math r typ args "tan"
  +        | _ -> None
  +
  +    let intrinsicFunctions com (i: Fabel.ApplyInfo) =
  +        match i.methodName, (i.callee, i.args) with
  +        | "GetArray", TwoArgs (ar, idx) -> Fabel.Get (ar, idx, i.returnType) |> Some
  +        | "SetArray", ThreeArgs (ar, idx, value) -> Fabel.Set (ar, Some idx, value, i.range) |> Some
  +        | _ -> None
  +
  +    let fsharpMap com (i: Fabel.ApplyInfo) =
  +        match i.methodName with
  +        | "add" -> Instance "set"
  +        | "containsKey" -> Instance "has"
  +        | "count" -> Getter "size"
  +        | "isEmpty" ->
               let op = Fabel.UnaryOp UnaryNot |> Fabel.Value
  -            Fabel.Apply (op, [info.callee.Value], false, info.returnType, info.range)
  +            Fabel.Apply (op, [i.callee.Value], false, i.returnType, i.range)
               |> Inline
  -        | "Item" -> Instance "get"
  -        | "Remove" -> Instance "delete"
  -        | "tryFind"
  -        | "TryFind" -> Instance "get"
  +        | "item" -> Instance "get"
  +        | "remove" -> Instance "delete"
  +        | "tryFind" -> Instance "get"
           | "empty" -> failwith "TODO"
           | "exists" -> failwith "TODO"
           | "filter" -> failwith "TODO"
  
positive.code: 
      let (|StartsWith|_|) pattern (str: string) =
          if str.StartsWith pattern then Some pattern else None
  
      let ident name =
          Fabel.IdentValue {name=name; typ=Fabel.UnknownType} |> Fabel.Value
  
negative.code: 
  module private CoreLibPass =
      open Util
  
      type MapKind = Static | Both
  
      // TODO: Decimal
      let mappings =
          dict [
              system + "Random" => ("Random", Both)
              fsharp + "Collections.List" => ("List", Both)
              fsharp + "Collections.Array" => ("Array", Both)
              fsharp + "Collections.Seq" => ("Seq", Both)
              system + "DateTime" => ("Time", Static)
              system + "TimeSpan" => ("Time", Static)
              system + "String" => ("String", Static)
              system + "Text.RegularExpressions.Regex" => ("RegExp", Static)
              genericCollections + "List" => ("ResizeArray", Static)
              genericCollections + "IList" => ("ResizeArray", Static)
              genericCollections + "Dictionary" => ("Dictionary", Static)
              genericCollections + "IDictionary" => ("Dictionary", Static)
              fsharp + "Collections.Set" => ("Set", Static)
              fsharp + "Collections.Map" => ("Map", Static)
          ]
  
  open Util
  
  let private astPass com (info: Fabel.ApplyInfo) =
      match AstPass.mappings with
      | ContainsKey info.ownerFullName f -> f com info
      | _ -> None
  
  let private coreLibPass com (info: Fabel.ApplyInfo) =
      match CoreLibPass.mappings with
      | ContainsKey info.ownerFullName (modName, kind) ->
          match kind, info.callee with
          | CoreLibPass.Both, Some callee -> 
              instanceCall info.range info.returnType info.methodName (callee, info.args)
          | _ ->
              staticArgs info.callee info.args
              |> fabelCoreLibCall com info.range info.returnType modName info.methodName
          |> Some
      | _ -> None
  
  let tryReplace (com: ICompiler) (info: Fabel.ApplyInfo) =
      match astPass com info with
      | Some res -> Some res
      | None -> coreLibPass com info
  