Можно ли написать синтаксическое расширение camlp4, которое дает вам доступ к последней привязке let в виде строки? - PullRequest
1 голос
/ 05 января 2012

У меня есть такой код:

  type boolean = T | F
  type  bexp = Const of boolean 
  |  Var of variable
  |  Bop of bop * bexp * bexp
  |  Not of bexp
  and bop = And | Or | Xor 
  and variable = { name: string; mutable value: boolean }

Позже, если я хочу создать переменную, мне нужно сделать:

let full         = Var({name ="full"; value  = F});;   

Я бы предпочел не повторять «полный» дважды и хотел бы придумать какой-нибудь интроспективный способ получить имя в виде строки. Я думаю, что camlp4 может работать для этого, но понятия не имею, с чего начать.

Так что, в конечном итоге, я бы хотел сделать что-то вроде:

let full          = Var({name = :letname:; value = F});;

Где: letname: заполнит текущую привязку let в виде строки вместо (в данном случае «full»). (синтаксис: letname: это просто предложение, другие идеи для синтаксиса, которые не будут конфликтовать с синтаксисом OCaml?)

Более краткий синтаксис, подобный этому, вероятно, будет предпочтительнее:

var full = F 

Который затем расширился бы до:

let full = Var({name = "full"; value = F});;

Можно ли это сделать с camlp4, и если да, то как мне это сделать?

(при дальнейшем рассмотрении синтаксис: letname: или что-то подобное было бы более универсальным и полезным в других областях)

Ответы [ 2 ]

3 голосов
/ 11 февраля 2012

Попробуйте следующее. В отдельном файле, например test.ml

(* A simple syntax extension for getting the name of an identifier. *) 
open Camlp4 

(* Create an ID for the macro*) 
module Id : Sig.Id = struct 
    let name = "let'"
    let version = "1.0" 
end 

module Make (Syntax : Sig.Camlp4Syntax) = struct 
    open Sig 
    include Syntax 

    (* Extend the syntax with a let' x=e1 in e2 construction*) 
    EXTEND Gram 
    expr: [ 
        [ "let'"; x = patt ; "=" ; e1=expr; "in"; e2=expr -> 
            let name=begin match x with
                | Ast.PaId (_,Ast.IdLid(_,name)) -> name
                | _ -> failwith "Require an identifier in a let' statement."
            end in
            <:expr<
                let $x$ = $e1$ in ($str:name$,$e2$)
            >>
        ] 
    ]; 
    END 
end 

module M = Register.OCamlSyntaxExtension(Id)(Make) 

Далее скомпилируйте с

 ocamlc -c -I +camlp4 dynlink.cma camlp4lib.cma -pp camlp4of.opt test.ml

На верхнем уровне

 ocaml dynlink.cma -I +camlp4 camlp4of.cma

Тогда

# #load "test03.cmo";;
# let' x=1 in x;;
- : string * int = ("x", 1)

Чтобы скомпилировать с расширением, создайте другой файл, например test2.ml

let' x=1 in x

Затем скомпилируйте с

ocamlc -pp "camlp4of test.cmo" test2.ml
0 голосов
/ 05 января 2012

Да, это возможно.Начните с чтения некоторого учебного пособия по camlp4, чтобы понять, как оно работает, и задавайте более конкретные вопросы.

...