Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design of Weasel #491

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions example/weasel/grammar.ebnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
(*
In the grammar below, the following notations are adopted:
- The nonterminal symbol `u32` denotes 32-bit unsigned integers.
- The nonterminal symbol `integer` denotes arbitrary-precision mathematical integers.
- The nonterminal symbol `real` denotes arbitrary-precision mathematical real numbers.
*)

idchar =
"0" | ... | "9"
| "A" | ... | "Z"
| "a" | ... | "z"
| "!" | "#" | "$" | "%" | "&" | "'" | "*" | "+" | "-" | "." | "/"
| ":" | "<" | "=" | ">" | "?" | "@" | "\" | "^" | "_" | "`" | "|" | "~" ;

id =
idchar , { idchar } ;

ind =
"$" , id
| u32 ;

unop =
"clz" (on wasm_int_type)
| "ctz" (on wasm_int_type)
| "popcnt" (on wasm_int_type)
| "abs"
| "neg"
| "sqrt"
| "ceil"
| "floor"
| "trunc" (on wasm_float_type or real)
| "nearst" ; (on wasm_float_type or real)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nearest

Copy link
Collaborator Author

@Laplace-Demon Laplace-Demon Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I included them mainly because they are present in WebAssembly. So these operations are free to get for floating point numbers, while extra work needs to be done for rational numbers.


binop =
"add" | "+"
| "sub" | "-"
| "mul" | "*"
| "div" | "/"
| "rem" | "%" (on wasm_int_type or integer)
| "min"
| "max"
| "and" | "&" (on wasm_int_type or integer)
| "or" | "|" (on wasm_int_type or integer)
| "xor" | "^" (on wasm_int_type or integer)
| "shl" | "<<" (on wasm_int_type or integer)
| "shr_s" | ">>" (on wasm_int_type or integer)
| "shr_x" | ">>>" (on wasm_int_type or integer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of these are quite unusual on mathematical integers, are there similar operators in WhyML/Gospel/ACSL?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, bitwise operations are implemented even on mathematical integers. But I agree that they may not be as useful.

For Gospel, see the stdlib and the pull request.

E-ACSL accomodates pure C expressions, and extends them on mathematical integers.

| "rotl" (on wasm_int_type)
| "rotr" (on wasm_int_type)
| "copysign" ;

memarg =
"(" , "base" , term , ")" ,
[ "(" , "offset" , term , ")" ] ,
[ "(" , "align" , term , ")" ] ;

term =
"result"
| "i32_max"
| "i32_min"
| "i64_max"
| "i64_min"
| integer
| real
| ind
| pterm ;

pterm =
"result" , [ u32 ]
| "old" , term
| "param" , ind
| "global" , ind
| "binder" , ind
| unop , term
| binop , term, term
| "null" , ref_type
| "ref_func" , ind
| "table_get" , ind
| "table_size" , ind
| "i32_load" , memarg
| "i64_load" , memarg
| "f32_load" , memarg
| "f64_load" , memarg
| "memory_size" , ind
| "?:" , term , term , term
| "let" , numerical_type , [ id ] , term , term
| "cast" , numerical_type , term
| (* function application *) ;

unpred =
"eqz"
| "is_null" ; (on ref_type)

binpred =
"eq" | "="
| "ne" | "!="
| "lt" | "<"
| "gt" | ">"
| "le" | "<="
| "ge" | ">=" ;

prop =
"true"
| "false"
| "(" , pprop , ")" ;

pprop =
"old" , prop
| "!" , prop
| "&&" , prop , prop
| "||" , prop , prop
| "^^" , prop , prop
| "==>" , prop , prop
| "<==>" , prop , prop
| "?:" , prop , prop , prop
| "let" , numerical_type , [ id ] , term , prop
| unpred , prop
| binpred , prop , prop
| ("forall" | "∀") , numerical_type , [ id ] , prop
| ("exists" | "∃") , numerical_type , [ id ] , prop
| (* predicate application *) ;

wasm_int_type =
"i32"
| "i64" ;

wasm_float_type =
"f32"
| "f64" ;

wasm_type =
wasm_int_type
| wasm_float_type ;

numerical_type =
wasm_type
| "integer"
| "real" ;

ref_type =
"funcref"
| "externref" ;

requires_clause = "(" , "requires" , prop , ")" ;

assigns_clause = "(" , "assigns" , ( "nothing" | memarg ) , ")" ;

ensures_clause = "(" , "ensures" , prop , ")" ;

simple_behavior = { requires_clause | assigns_clause | ensures_clause } ;

contract = "(@contract" , ind , simple_behavior , ")" ;

annotation = contract ;
7 changes: 7 additions & 0 deletions example/weasel/ill_formed.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(module
(@contract $f
owi
(ensures true)
)
(func $f)
)
49 changes: 49 additions & 0 deletions example/weasel/language design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Weasel: WebAssembly Specification Language

## Custom Annotations

Weasel specifications are written directly in WebAssembly's text format as [custom annotations](https://webassembly.github.io/annotations/core/text/lexical.html#annotations). Compared to comments, embedding specifications in custom annotations provides the benefit of syntax highlighting, while keeping the source file compatable with the WebAssembly specification.

Custom annotations take the form `(@annotid content)`, where there is no space between `(@` and `annotid`. `annotid` could either be a sequence of characters or a double-quoted string, and `content` should be well-parenthesized. It is possible to have nested custom annotations.

## Parser Behavior

Custom annotations may appear anywhere inside WebAssembly text format files where spaces are allowed. They do not interfere with the semantics of WebAssembly, and parsers are free to discard custom annotations.

For applications where certain custom annotations carry specific meanings, additional grammatical restrictions may be imposed on the content of custom annotations. Their behavior in case of an error are implementation-defined. For example, Owi's implementation of Weasel emits a syntax error when encountering an ill-formed function contract.

<!-- $MDX file=ill_formed.wat -->
```wat
(module
(@contract $f
owi
(ensures true)
)
(func $f)
)
```

```sh
$ owi instrument ill_formed.wat
unknown annotation clause owi
```

## Type of Annotation

In Weasel, `annotid` specifies the type of annotation. Different types of annotations follow slightly different grammatical rules and must appear in specific locations of the source code. Currently, Weasel define only one type of annotation:

- **function contract** should appear anywhere a module field is allowed (i.e. as a custom section). Though it is recommended to place the contract immediately before the corresponding function definition.

## Grammar

Weasel adopts an S-expression-like syntax for the time being, mainly because it is easy to prototype. The syntax may evolve in the future (to an infix one, possibly).

The grammar of Weasel annotations is specified [here](grammar.ebnf) in [EBNF-ISO form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form#Table_of_symbols).

## Future works

- big number
- variants of memory loads
- specification of loop invariant
- application of (pure) functions through call, call_indirect, call_ref
- make memory access syntax more lightweight
Loading