Zulip Chat Archive

Stream: new members

Topic: Tools for exploring data structures?


Eduardo Ochs (May 25 2024 at 11:25):

Hi all! I was trying to understand the data structures that are accessible inside a run_cmd, but this example - from this thread -

import Lean
namespace Foo
run_cmd Lean.logInfo ( Lean.getCurrNamespace)

turned out to be too complex... so I took this one,

open Lean
#eval Syntax.mkApp (mkIdent `Nat.add) #[Syntax.mkNumLit "1", Syntax.mkNumLit "1"]
#eval mkNode term_+_» #[Syntax.mkNumLit "1", mkAtom "+", Syntax.mkNumLit "1"]

from the section "Constructing new Syntax" of the metaprogramming book, and expanded it into:

open Lean

def my1      := Syntax.mkNumLit "1"
def myadd    := mkIdent `Nat.add
def myplus   := term_+_»
def myadd11  := Syntax.mkApp myadd #[my1, my1]
def myplus11 := mkNode myplus #[my1, mkAtom "+", my1]

-- Compare:
#eval Syntax.mkApp (mkIdent `Nat.add) #[Syntax.mkNumLit "1", Syntax.mkNumLit "1"]
#eval myadd11
#eval mkNode term_+_» #[Syntax.mkNumLit "1", mkAtom "+", Syntax.mkNumLit "1"]
#eval myplus11

-- Primitive tools for exploring myadd11 and myplus11:
class Foo (α : Type) where foo : α  String

def Syntax.foo : Syntax  String
  | .missing              => "(missing)"
  | .node  info kind args => "(node)"
  | .atom  info val       => "(atom)"
  | .ident info rawVal val preresolved => "(ident)"

def Name.foo : Name  String
  | .anonymous   => "(anonymous)"
--| .str pre str => "(str)"
  | .str pre str => "(str: "++ str ++ ")"
  | .num pre i   => "(num)"

instance : Foo Syntax where foo := Syntax.foo
instance : Foo Name   where foo := Name.foo

#eval Syntax.foo myplus11
#eval Syntax.foo myadd11
#eval Name.foo   myplus

With that I can see that myplus11 is an object of the class Syntax that is of the form "node info kind args", and by changing my definitions of Syntax.foo and Name.foo I should be able to inspect to interesting subfields and subsubfields of myplus11 and myadd11... but that looks very clumsy.

How do non-newbies inspect particular cases data structures? For example, what are the better ways to discover that myplus11 above is of an object of the class Syntax, of the form "node info kind args", and how would non-newbies extract its "info" field?

Chris Bailey (May 25 2024 at 17:09):

Eduardo Ochs said:

For example, what are the better ways to discover that myplus11 above is of an object of the class Syntax, of the form "node info kind args", and how would non-newbies extract its "info" field?

You can use the #check <arg> command to get the type of <arg>. #check myplus11 should show myplus11: TSyntax myplus in the info window.

Most people are either going to search the docs, or use vscode's right-click menu options, like to go definition and go to type definition.

Eduardo Ochs (May 26 2024 at 05:03):

It's hard to extract the values of subfields from the info window! I was looking for something that would let me extract the values of subfields and subsubfields and put them into variables, like this -

open Lean
def my1      := Syntax.mkNumLit "1"
def myadd    := mkIdent `Nat.add
def myplus   := term_+_»
def myadd11  := Syntax.mkApp myadd #[my1, my1]
def myplus11 := mkNode myplus #[my1, mkAtom "+", my1]

macro "extractFrom " input:term " => " pat:term " => " result:term : term =>
  `(match ($input) with
     | some ($pat) => some ($result)
     | _ => none)

def a := some myadd11
#check a
#eval  a
#check Term

def b := extractFrom a => Syntax.node info kind args => info
#check b
#eval  b

Note that the macro "extractFrom" above is buggy! It worked for me in a simpler case (not shown), but it doesn't work in the code above. I'll try to fix that tomorrow - more later...


Last updated: May 02 2025 at 03:31 UTC