/- Copyright (c) 2019 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ import Lean.Expr universe u namespace Lean class ToExpr (α : Type u) := (toExpr : α → Expr) (toTypeExpr : Expr) export ToExpr (toExpr toTypeExpr) instance : ToExpr Expr := { toExpr := id, toTypeExpr := mkConst `Expr } instance : ToExpr Nat := { toExpr := mkNatLit, toTypeExpr := mkConst `Nat } instance : ToExpr Bool := { toExpr := fun b => if b then mkConst `Bool.true else mkConst `Bool.false, toTypeExpr := mkConst `Bool } instance : ToExpr Char := { toExpr := fun c => mkApp (mkConst `Char.ofNat) (toExpr c.toNat), toTypeExpr := mkConst `Char } instance : ToExpr String := { toExpr := mkStrLit, toTypeExpr := mkConst `String } instance : ToExpr Unit := { toExpr := fun _ => mkConst `Unit.unit, toTypeExpr := mkConst `Unit } def Name.toExprAux : Name → Expr | Name.anonymous => mkConst `Lean.Name.anonymous | Name.str p s _ => mkAppB (mkConst `Lean.mkNameStr) (toExprAux p) (toExpr s) | Name.num p n _ => mkAppB (mkConst `Lean.mkNameNum) (toExprAux p) (toExpr n) instance : ToExpr Name := { toExpr := Name.toExprAux, toTypeExpr := mkConst `Name } instance {α : Type} [ToExpr α] : ToExpr (Option α) := let type := toTypeExpr α { toExpr := fun o => match o with | none => mkApp (mkConst `Option.none [levelZero]) type | some a => mkApp2 (mkConst `Option.cons [levelZero]) type (toExpr a), toTypeExpr := mkApp (mkConst `Option [levelZero]) type } def List.toExprAux {α} [ToExpr α] (nilFn : Expr) (consFn : Expr) : List α → Expr | [] => nilFn | a::as => mkApp2 consFn (toExpr a) (toExprAux nilFn consFn as) instance {α : Type} [ToExpr α] : ToExpr (List α) := let type := toTypeExpr α let nil := mkApp (mkConst `List.nil [levelZero]) type let cons := mkApp (mkConst `List.cons [levelZero]) type { toExpr := List.toExprAux nil cons, toTypeExpr := mkApp (mkConst `List [levelZero]) type } instance {α : Type} [ToExpr α] : ToExpr (Array α) := let type := toTypeExpr α { toExpr := fun as => mkApp2 (mkConst `List.toArray [levelZero]) type (toExpr as.toList), toTypeExpr := mkApp (mkConst `Array [levelZero]) type } instance {α : Type} {β : Type} [ToExpr α] [ToExpr β] : ToExpr (α × β) := let αType := toTypeExpr α let βType := toTypeExpr β { toExpr := fun ⟨a, b⟩ => mkApp4 (mkConst `Prod.mk [levelZero, levelZero]) αType βType (toExpr a) (toExpr b), toTypeExpr := mkApp2 (mkConst `Prod [levelZero, levelZero]) αType βType } end Lean