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

Implement final expressions #64

Merged
merged 6 commits into from
Aug 27, 2024
Merged
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
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ $(EXECUTION_OUTPUT_DIR)/%.run.executed.kore: $(EXECUTION_INPUT_DIR)/%.run $(RUST
krun \
"$(shell echo "$<" | sed 's/\.[^.]*.run$$//').rs" \
--definition $(RUST_EXECUTION_KOMPILED) \
--parser $(CURDIR)/parse-rust.sh \
--output kore \
--output-file $@.tmp \
-cTEST="$(shell cat $<)" \
-pTEST=$(CURDIR)/run-test.sh
-pTEST=$(CURDIR)/parse-test.sh
cat $@.tmp | grep -q "Lbl'-LT-'k'-GT-'{}(dotk{}())"
mv -f $@.tmp $@
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,19 @@ We will ignore: use declaratios, some attributes and macros.
We will not handle: extern crates, functions, type aliases,
enumerations, unions, static items, external blocks.

Int literals and casts
----------------------

Int literal [type determination](https://doc.rust-lang.org/stable/reference/expressions/literal-expr.html#integer-literal-expressions)

We will not implement explicit casts. However, int literals with a default type
are special in that they have some implicit casts determined by the context.

To implement that, we will follow the algorithm in the link above, converting
everything to `u128`, then we will do a conversion on the spot if something
else is required. This should mostly work, since we are relying on the Rust
compiler to check that int types are properly used.

Other things not discussed elsewhere
------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion deps/k_release
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.1.92
7.1.121
8 changes: 8 additions & 0 deletions parse-rust.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#! /bin/bash

kast \
--output kore \
--definition .build/rust-execution-kompiled \
--module RUST-COMMON-SYNTAX \
--sort Crate \
$1
File renamed without changes.
5 changes: 5 additions & 0 deletions rust-semantics/execution/block.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
```k

module RUST-BLOCK
imports RUST-REPRESENTATION
imports RUST-SHARED-SYNTAX
imports RUST-STACK

Expand All @@ -12,6 +13,10 @@ module RUST-BLOCK
// variable shadowing
rule {.InnerAttributes S:Statements}:BlockExpression
=> pushLocalState ~> S ~> popLocalState

// Blocks are always value expressions and evaluate the last operand in
// value expression context.
rule V:Value ~> popLocalState => popLocalState ~> V
endmodule

```
2 changes: 2 additions & 0 deletions rust-semantics/execution/calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ module RUST-CALLS
~> clearLocalState
~> setArgs(Args, Params)
~> FunctionBody
~> implicitCastTo(ReturnType)
~> popLocalState
...
</k>
<trait-path> TraitName </trait-path>
<method-name> MethodName </method-name>
<method-params> Params:NormalizedFunctionParameterList </method-params>
<method-return-type> ReturnType:Type </method-return-type>
<method-implementation> block(FunctionBody) </method-implementation>

rule
Expand Down
52 changes: 29 additions & 23 deletions rust-semantics/expression/casts.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,44 @@
module RUST-CASTS
imports private RUST-REPRESENTATION

syntax ValueOrError ::= cast(Value, Type) [function, total]
syntax ValueOrError ::= implicitCast(Value, Type) [function, total]

rule cast(V:Value, T:Type) => error("Unknown cast.", ListItem(V) ListItem(T))
rule implicitCast(V:Value, T:Type) => error("Unknown implicitCast.", ListItem(V) ListItem(T))
[owise]

// https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#numeric-cast
// https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#numeric-implicitCast

rule cast(i32(Value), i32) => i32(Value)
rule cast(i32(Value), u32) => u32(Value)
rule cast(i32(Value), i64) => i64(Int2MInt(MInt2Signed(Value)))
rule cast(i32(Value), u64) => u64(Int2MInt(MInt2Signed(Value)))
rule implicitCast(i32(Value), i32) => i32(Value)
rule implicitCast(i32(Value), u32) => u32(Value)
rule implicitCast(i32(Value), i64) => i64(Int2MInt(MInt2Signed(Value)))
rule implicitCast(i32(Value), u64) => u64(Int2MInt(MInt2Signed(Value)))

rule cast(u32(Value), i32) => i32(Value)
rule cast(u32(Value), u32) => u32(Value)
rule cast(u32(Value), i64) => i64(Int2MInt(MInt2Unsigned(Value)))
rule cast(u32(Value), u64) => u64(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u32(Value), i32) => i32(Value)
rule implicitCast(u32(Value), u32) => u32(Value)
rule implicitCast(u32(Value), i64) => i64(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u32(Value), u64) => u64(Int2MInt(MInt2Unsigned(Value)))


rule cast(i64(Value), i32) => i32(Int2MInt(MInt2Signed(Value)))
rule cast(i64(Value), u32) => u32(Int2MInt(MInt2Signed(Value)))
rule cast(i64(Value), i64) => i64(Value)
rule cast(i64(Value), u64) => u64(Value)
rule implicitCast(i64(Value), i32) => i32(Int2MInt(MInt2Signed(Value)))
rule implicitCast(i64(Value), u32) => u32(Int2MInt(MInt2Signed(Value)))
rule implicitCast(i64(Value), i64) => i64(Value)
rule implicitCast(i64(Value), u64) => u64(Value)

rule cast(u64(Value), i32) => i32(Int2MInt(MInt2Unsigned(Value)))
rule cast(u64(Value), u32) => u32(Int2MInt(MInt2Unsigned(Value)))
rule cast(u64(Value), i64) => i64(Value)
rule cast(u64(Value), u64) => u64(Value)
rule implicitCast(u64(Value), i32) => i32(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u64(Value), u32) => u32(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u64(Value), i64) => i64(Value)
rule implicitCast(u64(Value), u64) => u64(Value)

rule cast(u128(Value), i32) => i32(Int2MInt(MInt2Unsigned(Value)))
rule cast(u128(Value), u32) => u32(Int2MInt(MInt2Unsigned(Value)))
rule cast(u128(Value), i64) => i64(Int2MInt(MInt2Unsigned(Value)))
rule cast(u128(Value), u64) => u64(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u128(Value), i32) => i32(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u128(Value), u32) => u32(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u128(Value), i64) => i64(Int2MInt(MInt2Unsigned(Value)))
rule implicitCast(u128(Value), u64) => u64(Int2MInt(MInt2Unsigned(Value)))

// Rewrites

rule V:Value ~> implicitCastTo(T:Type) => implicitCast(V, T)
// We don't need a value for the unit type
rule implicitCastTo(( )) => .K

endmodule

Expand Down
2 changes: 1 addition & 1 deletion rust-semantics/preprocessing/constants.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module RUST-CONSTANTS

rule
(const Name:Identifier : T:Type = V:Value;):ConstantItem:KItem
=> setConstant(Name, cast(V, T))
=> setConstant(Name, implicitCast(V, T))

rule
<k>
Expand Down
36 changes: 22 additions & 14 deletions rust-semantics/representation.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
```k

module RUST-REPRESENTATION
imports INT
module RUST-VALUE-SYNTAX
imports LIST // for filling the second argument of `error`.
imports MAP
imports MINT
imports RUST-SHARED-SYNTAX
imports STRING

syntax MInt{8}
syntax MInt{16}
Expand All @@ -15,30 +15,38 @@ module RUST-REPRESENTATION

syntax SemanticsError ::= error(String, KItem)

syntax FunctionBodyRepresentation ::= block(BlockExpression)
| "empty"
| storageAccessor(StringLiteral)
syntax NormalizedFunctionParameter ::= Identifier ":" Type
syntax NormalizedFunctionParameterList ::= List{NormalizedFunctionParameter, ","}

syntax NormalizedCallParams ::=List{Int, ","}

syntax Instruction ::= normalizedMethodCall(TypePath, Identifier, NormalizedCallParams)

syntax NormalizedFunctionParameterListOrError ::= NormalizedFunctionParameterList | SemanticsError

syntax Value ::= i32(MInt{32})
| u32(MInt{32})
| i64(MInt{64})
| u64(MInt{64})
| u128(MInt{128})
| tuple(ValueList)
| struct(TypePath, Map) // Map from field name (Identifier) to value ID (Int)

syntax ValueList ::= List{Value, ","}
syntax Expression ::= Value
syntax KResult ::= Value

syntax ValueOrError ::= Value | SemanticsError
endmodule

module RUST-REPRESENTATION
imports INT
imports RUST-SHARED-SYNTAX
imports RUST-VALUE-SYNTAX

syntax FunctionBodyRepresentation ::= block(BlockExpression)
| "empty"
| storageAccessor(StringLiteral)
syntax NormalizedFunctionParameter ::= Identifier ":" Type
syntax NormalizedFunctionParameterList ::= List{NormalizedFunctionParameter, ","}

syntax NormalizedCallParams ::=List{Int, ","}

syntax Instruction ::= normalizedMethodCall(TypePath, Identifier, NormalizedCallParams)
| implicitCastTo(Type)

syntax NormalizedFunctionParameterListOrError ::= NormalizedFunctionParameterList | SemanticsError

syntax Type ::= "$selftype"

Expand Down
6 changes: 3 additions & 3 deletions rust-semantics/rust-common-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ https://doc.rust-lang.org/reference/items/extern-crates.html

```

https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-implicitCast-expressions

```k

Expand Down Expand Up @@ -952,15 +952,15 @@ https://doc.rust-lang.org/reference/items/extern-crates.html
//
// As an example, this means that you can't simply write
//
// rule cast(u64(Value), u64) => u64(Value)
// rule implicitCast(u64(Value), u64) => u64(Value)
//
// because that rule will compile just fine, but it will never apply at
// runtime because it uses an injection (why??? there is no injection
// available!), while the parser will produce actual TypePathSegments lists
// (the K rule will also produce lists from `u64` sometimes, I'm not yet sure
// when). Instead, you need to write
//
// rule cast(u64(Value), u64 :: .TypePathSegments) => u64(Value)
// rule implicitCast(u64(Value), u64 :: .TypePathSegments) => u64(Value)
//
// which will work, but you have to figure out all cases where this may happen
// without any help from the compiler.
Expand Down
12 changes: 12 additions & 0 deletions rust-semantics/test/execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

module RUST-EXECUTION-TEST-PARSING-SYNTAX
imports RUST-SHARED-SYNTAX
imports RUST-VALUE-SYNTAX

syntax ExecutionTest ::= NeList{ExecutionItem, ";"}
// syntax ExecutionTest ::= ExecutionItem ";" ExecutionItem
syntax ExecutionItem ::= "new" TypePath
| "call" TypePath "." Identifier
| "return_value"
| "check_eq" Expression [strict]
endmodule

module RUST-EXECUTION-TEST
Expand Down Expand Up @@ -61,6 +64,15 @@ module RUST-EXECUTION-TEST
Args:NormalizedCallParams,
0
) => normalizedMethodCall(TraitName, MethodName, Args)

rule
<k> (V:Value ~> return_value ; Es:ExecutionTest) => Es ... </k>
<test-stack> .List => ListItem(V) ... </test-stack>

rule
<k> check_eq V:Value => .K ... </k>
<test-stack> ListItem(V) => .List ... </test-stack>

endmodule

```
4 changes: 4 additions & 0 deletions tests/execution/final-expression.1.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
new FinalExpression;
call FinalExpression.constant;
return_value;
check_eq 100_u64
4 changes: 4 additions & 0 deletions tests/execution/final-expression.2.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
new FinalExpression;
call FinalExpression.constant_cast;
return_value;
check_eq 100_u64
18 changes: 18 additions & 0 deletions tests/execution/final-expression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![no_std]

#[allow(unused_imports)]
use multiversx_sc::imports::*;

#[multiversx_sc::contract]
pub trait FinalExpression {
#[init]
fn init(&self) {
}

#[upgrade]
fn upgrade(&self) {}

fn constant(&self) -> u64 { 100_u64 }

fn constant_cast(&self) -> u64 { 100 }
}
4 changes: 2 additions & 2 deletions tests/syntax/lending.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub trait Lending {
let token_amount = self.token_amount(&token).get();
let token_shares = self.token_shares(&token).get();

let shares =
let shares =
self.to_shares(
&amount,
&token_amount,
Expand All @@ -111,7 +111,7 @@ pub trait Lending {
let token_borrowed = self.token_borrowed(&token).get();
let token_borrowed_shares = self.token_borrowed_shares(&token).get();

let shares =
let shares =
self.to_shares(
&amount,
&token_borrowed,
Expand Down
Loading