Sukerujo: syntactic sugar over Dedukti
1. What is Sukerujo?
Sukerujo is an alternative parser for Dedukti bringing the following enhancements:
- literals for natural numbers in decimal notation
- literals for characters
- literals for strings
- literals for polymorphic lists
- local (let) definitions
- recursive records
Sukerujo is developed by Raphaƫl Cauderlier.
2. Get Sukerujo
3. Usage
Sukerujo is invoked by the command skcheck
accepting the same
arguments as Dedukti type-checker dkcheck
.
Sukerujo files typically have the extension
.sk
. They can be converted to unsugared Dedukti .dk
files by the
following command:
$ skindent my_file.sk > my_file.dk
If you want to use Sukerujo literals, you need to declare the corresponding types and functions used to build the terms in a regular Dedukti file. This file can have any name but should compile to builtins.dko
. Moreover, the .dko
file should be readable by skcheck
, which in practice means that you should either use the version of skcheck
corresponding to the version of dkcheck
used to compile builtins.dko
or use skcheck
in backward-compatibility mode (option -nk
) to compile the file declaring the builtins constants.
4. Example
File builtins.dk
:
#NAME builtins. nat : Type. 0 : nat. S : nat -> nat. list : Type -> Type. nil : A : Type -> list A. cons : A : Type -> A -> list A -> list A. char : Type. char_of_nat : nat -> char. string : Type. string_nil : string. string_cons : char -> string -> string.
File example.sk
:
#NAME example. def string_length : string -> nat. [] string_length "" --> 0 [c, s] string_length (string_cons c s) --> S (string_length s). #CONV string_length "Hello World!", 12.
Compilation and checking:
$ dkcheck -e -coc builtins.dk SUCCESS File 'builtins.dk' was successfully checked. $ skcheck example.sk YES SUCCESS File 'example.sk' was successfully checked.
5. Detailed description
5.1. Grammar
5.1.1. Lexical classes
Tokens are separated by any positive number of whitespace characters
(spaces, tabulations, newlines, and carriage return). Comments are
delimited by (;
and ;)
; they cannot be nested.
Numbers are written in decimal notation, the first digit must be non-zero.
Character literals are delimited by single quotes (').
String literals are delimited by double quotes (").
The following are reserved keywords: .
, , , :
, ==
, [
, ]
,
{
, }
, (
, )
, -->
, ->
, =>
, :=
, _
, Record
, Type
,
def
, thm
, %typeof
, #NAME
, #REQUIRE
, #EVAL
, #INFER
,
#CHECK
, #CHECKNOT
, #ASSERT
, #ASSERTNOT
, #PRINT
, #GDT
.
The following are builtin constants: nat
, 0
, S
, char
,
char_of_nat
, string
, string_cons
, list
, nil
, cons
.
Identifiers are any non-empty sequence of ASCII letters (uppercase and
lowercase), digits, underscore (_
), exclamation mark (!
), question
mark (?
) and apostrophe (') such that the first character is not
an apostrophe and which is not one of the reserved keywords nor a
builtin constant.
Qualified identifiers are composed of a module name (a non-empty
sequence of letters, digits, and underscore) followed by a period
(.
) and by an identifier.
<number> :== [1-9][0-9]* <char> :== ['].['] <string> :== ["].*["] <id> :== [_a-zA-Z0-9!?][_a-zA-Z0-9!?']* <mid> :== [_a-zA-Z0-9]+ <qid> :== <mid>[.]<id>
5.1.2. Grammar rules
This is a slightly simplified and ambiguous presentation of the syntax
of Sukerujo. For the exact grammar, see the file
parser/menhir_parser.mly
.
term ::= <qid> | <id> | '(' term ')' | 'Type' // The sort of all types | <number> | <char> | <string> | term+ | <id> ':=' term '=>' term // Local definition | [<id> ':']? term '->' term // Product | <id> [: ['_' | term]]? '=>' term // Abstraction | '%typeof' term // Type of a term pattern ::= [<id> | <qid>] pattern* | '_' // Universal pattern | '{' term '}' // Guard | '(' pattern ')' | <id> '=>' pattern // Higher-order pattern param ::= '(' <id> ':' term ')' | '(' <id> ':=' term ')' eval_config ::= '[' <id> [, <id>]? ']' decl ::= <id> [':' term]? def_decl ::= <id> ':' term rule ::= ['{' <id> | <qid> '}']? '[' [decl [',' decl]*]? ']' [<id> | <qid>] pattern* '-->' term '.' // An optional name enclosed by '{' and '}', followed by the rule // context, the left-hand-side pattern and the right-hand-side term line ::= <id> ['(' <id> ':' term ')']* ':' term '.' // Static declaration | 'def' <id> ':' term '.' // Definable declaration | ['def' | 'thm'] <id> param* [':' term]? ':=' term '.' // Definition | 'Record' <id> param* ':=' <id> '{' [def_decl [',' def_decl]*]? '}' '.' // Record type declaration | rule+ '.' // Rewrite rule | ['#EVAL' | '#INFER'] eval_config? term '.' | ['#CHECK' | '#CHECKNOT' | '#ASSERT' | '#ASSERTNOT'] term [ ':' | '==' ] term '.' | '#PRINT' <string> '.' | '#GDT' [<id> | <qid>] '.' | ['#NAME' | '#REQUIRE'] <mid> '.'