crucible-syntax: A syntax for reading and writing Crucible control-flow graphs

[ bsd3, language, library ] [ Propose Tags ] [ Report a vulnerability ]

This package provides a syntax for directly constructing Crucible control-flow graphs, as well as for observing them.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.4.1
Change log CHANGELOG.md
Dependencies base (>=4.9 && <4.20), bv-sized (>=1.0.0), containers, crucible (>=0.1), lens, megaparsec (>=7.0 && <9.7), mtl, parameterized-utils (>=0.1.7), prettyprinter (>=1.7.0), text, transformers, vector, what4 [details]
License BSD-3-Clause
Author Galois Inc.
Maintainer dtc@galois.com
Category Language
Uploaded by sauclovian_g at 2025-03-21T23:51:23Z
Distributions
Reverse Dependencies 1 direct, 2 indirect [details]
Downloads 5 total (5 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2025-03-22 [all 1 reports]

Readme for crucible-syntax-0.4.1

[back to package description]
This project defines a concrete syntax for a certain subset of the
registerized Crucible CFGs.

Some features are intentionally omitted, because they require
compile-time additions to Crucible in the form of type class
instances. In particular, there is no syntax for:

 * Recursive types

 * Extensions

 * Concrete types


How to use


General syntax

The basic syntax is based on a simplified variant of Lisp
S-expressions, without support for dotted pairs or special syntax for
quote or quasiquote. A syntactic form is either an atom or matching
opening and closing parentheses with a whitespace-delimited sequence
of syntactic forms between them.


The atoms are as follows:

 * Identifiers are either keywords or Crucible atom names. Every
   identifier that is not a language keyword is a Crucible atom
   name. Identifiers consist of a letter-like character followed by
   zero or more digits or letter-like characters. Letter-like
   characters are those considered letters by Unicode, or any of the
   characters <, >, =, +, -, *, /, !, _, \, or ?.

   The keywords are documented below, under each special form.

 * Function names consist of an @ character followed by an identifier.

 * Register names consist of a $ character followed by an identifier.

 * Numbers consist of an optional '+' or '-' followed by an unsigned
   number and an optional denominator. Unsigned numbers are either
   decimal literals, octal literals, or hexadecimal literals, using
   the typical syntax with a 0-prefix. A denominator is a '/'
   character followed by an unsigned number.

 * Boolean literals are #t or #T and #f or #F.

 * String literals are delimited by double-quotes, and support
   escaping with \.


Line comments are preceded by ;, and block comments are delimited by
#| and |#.


Functions

A program consists of a sequence of function definitions. A function
definition is a form that begins with the keyword "defun", followed by
a function name, argument list, return type, and body. A function name
is a function name atom. An argument list is a form that contains zero
or more argument specs. An argument spec is a two-element form, where
the first is a Crucible atom name, and the second is a form that
denotes a type. A return type is a form that denotes a type.

A function body consists of an optional list of registers, a start
block, and zero or more further blocks. A list of registers is a form
that begins with the keyword "registers" and is followed by zero or
more register specifications. A register specification is a form
containing an atom name and a type.

Blocks consist of the defblock keyword followed by a block body. Block
bodies are zero or more ordinary statements followed by a terminating
statement. The first block must begin with "start" instead of
"defblock". In the future, the restriction that the start block comes
first may be relaxed.

Forward declarations

A forward declaration is a form that begins with the keyword "declare",
followed by a function name, argument list, and return type. A forward
declaration is like a function but without the function body. Forward
declarations are useful in situations where you do not know the definition
of a function ahead of time, but you will know it at some point after parsing
the program. It is the responsibility of the client to ensure that forward
declarations are resolved to Crucible definitions before being invoked.

Global variables

A global variable is a form that begins with the keyword "defglobal", followed
by an identifier prefixed with two dollar signs (e.g., $$global-name) as well
as a type. A global variable is a mutable reference that scopes over all of the
functions defined in the program. The value of a global variable can be set
with the "set-global!" form.

A program can reference a global variable defined externally by using an extern
declaration. An extern declaration is exactly like a "defglobal" declaration,
but using the "extern" keyword instead of "defglobal". The difference between
an extern and a normal global variable is that the value of an extern may
already have been set by the time that the .cbl file which declares the extern
uses it. It is the responsibility of the client to ensure that externs are
inserted into the Crucible symbolic global state before being accessed.

Types

si ::= 'Unicode' | 'Char16' | 'Char8'

fi ::= 'Half' | 'Float' | 'Double' | 'Quad'
     | 'X86_80' | 'DoubleDouble'

t ::= 'Any' | 'Unit' | 'Bool' | 'Nat' | 'Integer' | 'Real'
    | 'ComplexReal' | 'Char' | '(' 'String' si ')'
    | '(' 'FP' fi ')' | '(' 'BitVector' n ')'
    | '(' '->' t ... t ')' | '(' 'Maybe' t ')'
    | '(' 'Sequence' t ')' | '(' 'Vector' t ')' | '(' 'Ref' t ')'
    | '(' 'Struct' t ... t ')' | '(' 'Variant' t ... t ')'


Expressions



Registers


Blocks


Statements