Skip to content

Commit

Permalink
Struct objects (#150)
Browse files Browse the repository at this point in the history
* Top level functions (#147) (#149)

* Refactor methods

* Run global functions

* Tests for top level fn without args

* External blocks

Co-authored-by: Virgil <[email protected]>

* adding the declaration of structs

* Adding declaration of tests

* Enabling parsing by having struct expressions

* Introducing struct creations

* Adding tests

* Partially addressing the PR review

* Fixing Struct syntax not matching reference

* Adapting the struct expressions to be closer to the reference

* Adding missing comment

* Addressing PR review

---------

Co-authored-by: Virgil <[email protected]>
  • Loading branch information
ACassimiro and virgil-serbanuta authored Oct 9, 2024
1 parent d579e16 commit 3e4b57e
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 3 deletions.
81 changes: 81 additions & 0 deletions rust-semantics/expression/struct.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,89 @@ module RUST-EXPRESSION-STRUCT
imports private RUST-CONVERSIONS-SYNTAX
imports private RUST-ERROR-SYNTAX
imports private RUST-EXECUTION-CONFIGURATION
imports private RUST-PREPROCESSING-CONFIGURATION
imports private RUST-REPRESENTATION
// For freezing heating operations, when leaving a struct alone in the topcell, make it a ptrValue
rule <k> struct(P, Fields) => ptrValue(null, struct(P, Fields)) ... </k>
// KItems for breaking down struct expressions into the adequate format struct(P, F)
syntax KItem ::= fromStructExpressionWithLiteralsBuildFieldsMap(TypePath, StructBases, List, Map)
| fromStructExpressionWithAssignmentsBuildFieldsMap(TypePath, StructExprFields, Map)
// From Struct Expression to struct(P, F). Case 1, field names are not given:
rule <k>
I:TypePath { L:StructBases } => fromStructExpressionWithLiteralsBuildFieldsMap(I, L, VL, .Map)
...
</k>
<struct-path> I </struct-path>
<field-list> VL </field-list>
rule <k> fromStructExpressionWithLiteralsBuildFieldsMap(I:TypePath, (E:Expression, RL):StructBases, FieldNameList:List, FieldsMap:Map)
=> E ~> fromStructExpressionWithLiteralsBuildFieldsMap(I, RL, FieldNameList, FieldsMap) ...
</k>
rule
<k>
ptrValue(_, V:Value):PtrValue ~>
fromStructExpressionWithLiteralsBuildFieldsMap(
I:TypePath,
RL:StructBases,
(FieldNameList):List ListItem(FieldName),
FieldsMap:Map)
=> fromStructExpressionWithLiteralsBuildFieldsMap(I, RL, FieldNameList, FieldsMap (FieldName |-> NVI):Map )
...
</k>
<values> VALUES:Map => VALUES[NVI <- V] </values>
<next-value-id> NVI:Int => NVI +Int 1 </next-value-id>
requires notBool (FieldName in_keys(FieldsMap))
rule <k>
fromStructExpressionWithLiteralsBuildFieldsMap(I:TypePath, .StructBases, .List, FieldsMap:Map)
=> struct(I, FieldsMap)
...
</k>
// From Struct Expression to struct(P, F). Case 2, field names are given:
rule <k>
I:TypePath { S:MaybeStructExprFieldsOrStructBase } => fromStructExpressionWithAssignmentsBuildFieldsMap(I, S, .Map)
...
</k>
rule <k>
fromStructExpressionWithAssignmentsBuildFieldsMap(
Name:TypePath,
((FieldName:Identifier : LE:Expression):StructExprField, RS):StructExprFields,
FieldsMap:Map)
=> LE ~> FieldName ~> fromStructExpressionWithAssignmentsBuildFieldsMap(Name, RS, FieldsMap)
...
</k>
rule <k>
ptrValue(_, V:Value):PtrValue ~> FieldName:Identifier ~>
fromStructExpressionWithAssignmentsBuildFieldsMap(
Name:TypePath,
RS:StructExprFields,
FieldsMap:Map
) =>
fromStructExpressionWithAssignmentsBuildFieldsMap(
Name, RS, FieldsMap (FieldName |-> NVI):Map
)
...
</k>
<values> VALUES:Map => VALUES[NVI <- V] </values>
<next-value-id> NVI:Int => NVI +Int 1 </next-value-id>
rule <k> fromStructExpressionWithAssignmentsBuildFieldsMap(
Name:TypePath,
.StructExprFields,
FieldsMap:Map
) => struct(Name, FieldsMap)
...
</k>
rule
<k>
normalizedMethodCall
Expand Down
13 changes: 13 additions & 0 deletions rust-semantics/preprocessing/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ module RUST-PREPROCESSING-CONFIGURATION
<constant-value> tuple(.ValueList) </constant-value>
</constant>
</constants>
<struct-list> .List </struct-list>
<structs>
<struct multiplicity="*" type="Map">
<struct-path> my_identifier:TypePath </struct-path>
<field-list> .List </field-list> // List of Identifier
<fields>
<field multiplicity="*" type="Map">
<field-name> .Identifier </field-name>
<field-type> ():Type </field-type>
</field>
</fields>
</struct>
</structs>
<trait-list> .List </trait-list> // List of TypePath
<traits>
<trait multiplicity="*" type="Map">
Expand Down
6 changes: 6 additions & 0 deletions rust-semantics/preprocessing/crate.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ module CRATE
=> (Atts Is):Crate
, CratePath:TypePath
)
rule (.K => structInitializer(S:Struct, CratePath))
~> crateParser
( (Atts:InnerAttributes (_ItemAtts:OuterAttributes _:MaybeVisibility S:Struct):Item Is:Items):Crate
=> (Atts Is):Crate
, CratePath:TypePath
)
rule crateParser( (_Atts:InnerAttributes .Items):Crate, _Path:TypePath)
=> .K //resolveCrateNames(Path)
Expand Down
35 changes: 35 additions & 0 deletions rust-semantics/preprocessing/initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,41 @@ module INITIALIZATION
imports private RUST-PREPROCESSING-PRIVATE-HELPERS
imports private RUST-PREPROCESSING-PRIVATE-SYNTAX
rule
<k> structInitializer( (struct Name:Identifier { F:StructFields } ):Struct, ParentPath:TypePath) => structParser(append(ParentPath, Name), F:StructFields )
...
</k>
<struct-list> .List => ListItem(append(ParentPath, Name)) ...</struct-list>
<structs>
...
.Bag
=> <struct>
<struct-path> append(ParentPath, Name) </struct-path>
...
</struct>
</structs>
rule
<k> structParser(Name:TypePath, ((FN:Identifier : FT:Type):StructField , RF:StructFields):StructFields) =>
structParser(Name:TypePath, RF:StructFields)
...
</k>
<struct>
...
<struct-path> Name </struct-path>
<field-list> L:List => ListItem(FN) L </field-list>
<fields>
.Bag =>
<field>
<field-name> FN </field-name>
<field-type> FT </field-type>
</field>
...
</fields>
</struct>
rule structParser(_Name:TypePath, .StructFields) => .K
rule
<k> traitInitializer(Name:TypePath, Atts:OuterAttributes) => .K
...
Expand Down
3 changes: 3 additions & 0 deletions rust-semantics/preprocessing/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ module RUST-PREPROCESSING-PRIVATE-SYNTAX
| externBlockParser(ExternBlock, TypePath)
| resolveCrateNames(TypePath)
syntax Initializer ::= structInitializer(Struct, TypePath)
| structParser(TypePath, StructFields)
syntax Initializer ::= addMethod(traitName : TypePath, function: Function, atts:OuterAttributes)
| #addMethod(
TypePath,
Expand Down
27 changes: 24 additions & 3 deletions rust-semantics/rust-common-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,13 @@ https://doc.rust-lang.org/reference/items/extern-crates.html
https://doc.rust-lang.org/reference/items/structs.html

```k
syntax Struct ::= "TODO: not needed yet, not implementing"
syntax Struct ::= StructStruct | TupleStruct
syntax TupleStruct ::= "TODO: not needed yet, not implementing"
syntax StructStruct ::= "struct" Identifier MaybeGenericParams MaybeWhereClause "{" MaybeStructFields "}"
syntax MaybeStructFields ::= "" | StructFields
syntax StructFields ::= List{StructField, ","}
syntax StructField ::= OuterAttributes MaybeVisibility Identifier ":" Type //TODO: Outerfields and visibility for
//struct fields is not yet supported.
```

Expand Down Expand Up @@ -540,7 +545,23 @@ https://doc.rust-lang.org/reference/items/extern-crates.html

```k
syntax StructExpression ::= "TODO: not needed yet, not implementing"
syntax StructExpression ::= StructExprStruct
| StructExprTuple
| StructExprUnit
syntax StructExprStruct ::= TypePath "{" MaybeStructExprFieldsOrStructBase "}" //TODO: Not implemented properly
//Should use PathInExpression instead of
//TypePath.
syntax MaybeStructExprFieldsOrStructBase ::= "" | StructExprFields | StructBases //TODO: Not implemented properly
//StructBases should be
//singular. and its correct
//value is: StructExprField (, StructExprField)* (, StructBase | ,?)
syntax StructExprFields ::= NeList{StructExprField, ","}
syntax StructBases ::= NeList{StructBase, ","}
syntax StructExprField ::= Identifier ":" Expression //TODO: Not implemented properly. Needs outer attributes.
syntax StructBase ::= Expression //TODO: Not implemented properly. Actual value should be '".." Expression'
syntax StructExprUnit ::= "TODO: not needed yet, not implementing"
syntax StructExprTuple ::= "TODO: not needed yet, not implementing"
```

Expand Down
4 changes: 4 additions & 0 deletions tests/execution/structs.1.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
new :: structs :: StructFile;
call :: structs :: StructFile.struct_with_var_assignment;
return_value;
check_eq 2_u32
4 changes: 4 additions & 0 deletions tests/execution/structs.2.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
new :: structs :: StructFile;
call :: structs :: StructFile.struct_without_var_assignment;
return_value;
check_eq 3_u32
36 changes: 36 additions & 0 deletions tests/execution/structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#![no_std]

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

struct Pair{i: u32, j: u32 }
struct Triple{i: u32, j: u32, k: u32 }

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

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

fn struct_with_var_assignment(&self) -> u32 {
let _pair = ::structs::Pair {
i: 1_u32,
j: 2_u32
};
let x = _pair.j;
x
}

fn struct_without_var_assignment(&self) -> u32 {
let _triple = ::structs::Triple {
1_u32,
2_u32,
3_u32
};
let x = _triple.k;
x
}
}

0 comments on commit 3e4b57e

Please sign in to comment.